Skip to content

3D Ball-Linear-Cushion Detection#350

Open
derek-mcblane wants to merge 13 commits into
ekiefl:mainfrom
derek-mcblane:dm/3d-linear-cushion-detection
Open

3D Ball-Linear-Cushion Detection#350
derek-mcblane wants to merge 13 commits into
ekiefl:mainfrom
derek-mcblane:dm/3d-linear-cushion-detection

Conversation

@derek-mcblane

@derek-mcblane derek-mcblane commented May 25, 2026

Copy link
Copy Markdown
Collaborator

Adding 3D detection support for ball-linear-cushion to resolve #303.

Summary by CodeRabbit

  • New Features

    • Improved collision detection for linear cushions so results now account for 3D ball motion.
  • Bug Fixes

    • Fixed event timing so cushion collisions are evaluated consistently in both 2D and 3D modes.
    • Improved how valid collision points are selected, reducing incorrect or missed cushion-hit events.
    • Enhanced root handling to better distinguish real collision times from invalid candidates.

@coderabbitai

coderabbitai Bot commented May 25, 2026

Copy link
Copy Markdown

Review Change Stack

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 67d49bae-9070-499f-a099-d94867154a40

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Walkthrough

Adds 3D ball-linear-cushion collision detection by rotating the ball's 3D position polynomial into the cushion's local frame, reducing the problem to a 2D parabola-vs-circle quartic, and filtering roots by segment bounds and approach direction. New math helpers (is_real_number, parabola_circle_distance_2d_quartic_coefficients) support this. get_next_ball_linear_cushion_event gains an is_3d flag wired through EventDetector.

Changes

3D Linear-Cushion Collision Detection

Layer / File(s) Summary
Math helpers
pooltool/ptmath/roots/core.py, pooltool/ptmath/roots/__init__.py, pooltool/evolution/event_based/detect/quartic_coefficients.py
Adds Numba-jitted is_real_number (complex-number realness check with abs/rel tolerance) and parabola_circle_distance_2d_quartic_coefficients (5-coefficient quartic for 2D parabola-vs-circle distance); is_real_number is re-exported via roots/__init__.py.
3D collision-time logic
pooltool/evolution/event_based/detect/ball_cushion.py
Imports quaternion; adds select_ball_linear_cushion_segment_collision_root (filters roots by segment bounds and dot-product approach direction) and ball_linear_cushion_segment_collison_time (rotates ball polynomial into cushion frame, solves quartic/quadratic, selects earliest root); updates get_next_ball_linear_cushion_event signature with keyword-only is_3d and branches on it.
Event detector wiring
pooltool/evolution/event_based/detect/detector.py
Passes is_3d=self.is_3d to get_next_ball_linear_cushion_event in EventDetector.get_next_event.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related issues

Possibly related PRs

  • ekiefl/pooltool#300: Previously disabled 3D linear-cushion events by returning null_event(np.inf); this PR replaces that stub with the actual implementation.
  • ekiefl/pooltool#327: Refactored cushion event/solver functions in ball_cushion.py and detector.py, directly preceding the is_3d routing added here.

Suggested reviewers

  • ekiefl
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title is concise and accurately captures the main change: adding 3D ball-linear-cushion detection.
Linked Issues check ✅ Passed The changes align with #303 by implementing 3D linear-cushion detection via a rotated local frame and segment-bound filtering.
Out of Scope Changes check ✅ Passed The added root and quartic helper code appears directly supportive of the 3D cushion-detection work, with no clear unrelated changes.
Docstring Coverage ✅ Passed Docstring coverage is 85.71% which is sufficient. The required threshold is 80.00%.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@derek-mcblane
derek-mcblane force-pushed the dm/3d-linear-cushion-detection branch from 2a6f0f6 to dc20aa3 Compare May 25, 2026 21:55
@derek-mcblane

derek-mcblane commented May 26, 2026

Copy link
Copy Markdown
Collaborator Author
  • Still need to limit detections to the length of the cushion segment

@derek-mcblane
derek-mcblane force-pushed the dm/3d-linear-cushion-detection branch from dc20aa3 to 274326c Compare May 26, 2026 01:37
@codecov

codecov Bot commented May 26, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 48.21429% with 29 lines in your changes missing coverage. Please review.
✅ Project coverage is 47.77%. Comparing base (9a8abfe) to head (bc74523).

Files with missing lines Patch % Lines
...ltool/evolution/event_based/detect/ball_cushion.py 57.89% 16 Missing ⚠️
pooltool/ptmath/roots/core.py 20.00% 8 Missing ⚠️
...olution/event_based/detect/quartic_coefficients.py 28.57% 5 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #350      +/-   ##
==========================================
+ Coverage   47.75%   47.77%   +0.02%     
==========================================
  Files         159      159              
  Lines       10716    10758      +42     
==========================================
+ Hits         5117     5140      +23     
- Misses       5599     5618      +19     
Flag Coverage Δ
service 47.77% <48.21%> (+0.02%) ⬆️
service-no-ani 58.12% <48.21%> (-0.03%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@derek-mcblane
derek-mcblane force-pushed the dm/3d-linear-cushion-detection branch from 274326c to 65bb7c0 Compare June 6, 2026 01:39
@derek-mcblane
derek-mcblane force-pushed the dm/3d-linear-cushion-detection branch from 65bb7c0 to fbddc7b Compare June 17, 2026 02:29
@derek-mcblane
derek-mcblane force-pushed the dm/3d-linear-cushion-detection branch from fbddc7b to 42923c9 Compare June 17, 2026 02:30
@derek-mcblane
derek-mcblane marked this pull request as ready for review June 17, 2026 02:35
@derek-mcblane
derek-mcblane requested a review from ekiefl as a code owner June 17, 2026 02:35
@ekiefl

ekiefl commented Jun 28, 2026

Copy link
Copy Markdown
Owner

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jun 28, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@pooltool/evolution/event_based/detect/ball_cushion.py`:
- Around line 67-114: The new 3D collision path in
ball_linear_cushion_segment_collison_time ignores cushion.direction, so
one-sided cushions become hittable from both sides. Add the same direction-side
filtering used by the legacy linear-cushion solver after selecting the collision
root, or before returning from
select_ball_linear_cushion_segment_collision_root, and make sure the check is
applied in the is_3d=True branch for LinearCushionSegment.
- Around line 91-95: The first 3D detection path in ball_cushion uses
parabola_circle_distance_2d_quartic_coefficients with only a single rotated
coordinate from p_rotated.T and cushion_origin_rotated, but that helper indexes
both xy[1] and center[1]. Update the call site to pass both rotated XY
components (not a 1-element slice) so the quartic builder receives valid 2D
inputs, and keep the change localized to the ball_cushion detection logic around
the parabola_circle_distance_2d_quartic_coefficients call.
- Around line 53-61: The approach check in ball_cushion.py is using an incorrect
velocity expression from the polynomial coefficients, which can misclassify
collisions. Update the collision test in the detection logic around
ball_position_polynomial() / the root loop so the velocity used for the dot
product reflects the true time derivative, using the same p coefficients that
define the position polynomial. Keep the existing root filtering and normal
calculation, but replace the current v / v_collision computation with the
correct derivative-based velocity before evaluating the approach check.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 7d02582d-9a63-4191-a131-909a04bea39d

📥 Commits

Reviewing files that changed from the base of the PR and between d44f812 and 9a5b16d.

📒 Files selected for processing (5)
  • pooltool/evolution/event_based/detect/ball_cushion.py
  • pooltool/evolution/event_based/detect/detector.py
  • pooltool/evolution/event_based/detect/quartic_coefficients.py
  • pooltool/ptmath/roots/__init__.py
  • pooltool/ptmath/roots/core.py

Comment thread pooltool/evolution/event_based/detect/ball_cushion.py Outdated
Comment thread pooltool/evolution/event_based/detect/ball_cushion.py Outdated
Comment thread pooltool/evolution/event_based/detect/ball_cushion.py
ekiefl and others added 10 commits June 28, 2026 12:33
- I have no idea why this worked before
select_ball_linear_cushion_segment_collision_root used v1 = 0.5 * p[2]
for the t-dependent term of the velocity, but p[2] is the t^2 coefficient
of the position polynomial (half the acceleration), so the velocity is
v(t) = p[1] + 2 * p[2] * t. The factor was off by 4x, which could flip
the sign of the dot(xy_normal, v_collision) "moving toward cushion" gate
and cause a valid approaching collision to be skipped or a receding root
to be wrongly accepted.

@ekiefl ekiefl left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Looks good @derek-mcblane!

I found some bugs that I'm 99% sure on, so I went ahead and fixed them--but I'd appreciate a second look.

142c3e2 sends x and y explicitly. I'm very surprised it worked with [0:1], and Claude thinks it was due to a slice memory vs contiguous array.

b29efe7 I'm not sure if you purposefully used np.isclose, but I made it exact to match ball-ball detection. We may need to add some tolerance in the future, but I'd rather introduce tolerance as needed and not relying on np.isclose defaults for absolute/relative tolerance.

@ekiefl

ekiefl commented Jun 29, 2026

Copy link
Copy Markdown
Owner

Oh, and also, thanks for your patience. Time has been hard to come by recently.

@derek-mcblane

Copy link
Copy Markdown
Collaborator Author

Looks good @derek-mcblane!

I found some bugs that I'm 99% sure on, so I went ahead and fixed them--but I'd appreciate a second look.

142c3e2 sends x and y explicitly. I'm very surprised it worked with [0:1], and Claude thinks it was due to a slice memory vs contiguous array.

b29efe7 I'm not sure if you purposefully used np.isclose, but I made it exact to match ball-ball detection. We may need to add some tolerance in the future, but I'd rather introduce tolerance as needed and not relying on np.isclose defaults for absolute/relative tolerance.

Ooops, I fixed these in another branch and they didn't make it to this one. Sorry for the trouble.

@derek-mcblane

Copy link
Copy Markdown
Collaborator Author

Oh, and also, thanks for your patience. Time has been hard to come by recently.

Don't sweat it


v0 = p[1]
v1 = 0.5 * p[2]
v1 = 2 * p[2]

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

This is correct. I guess I forgot how to take a derivative.

Comment on lines +53 to +54
v = np.array([p[1], 0.5 * p[2]])
v0 = p[1]
v1 = 0.5 * p[2]

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Could put v together outside of this function, instead. It might also make sense to construct it similar to ball_position_polynomial instead of taking a derivative.

@ekiefl

ekiefl commented Jul 7, 2026

Copy link
Copy Markdown
Owner

Hey I'm phone-bound until next week but it looks like this is good to merge. Agreed?

@derek-mcblane

Copy link
Copy Markdown
Collaborator Author

Hey I'm phone-bound until next week but it looks like this is good to merge. Agreed?

I'd like to find the branch I made those fixes on and see if there's anything else I missed so they don't get lost. Should be able to this weekend.

If there's anything being held up by this feel free to merge and I can do the checks after. Otherwise, let's leave it open.

@ekiefl

ekiefl commented Jul 9, 2026

Copy link
Copy Markdown
Owner

That sounds good to me! Was just checking in to make sure I wasn't blocking anything

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[support-3d] A2. 3D ball-linear-cushion detection

2 participants