Skip to content

Allow user-provided vertex and edge areas in CollisionMesh - #273

Merged
zfergus merged 3 commits into
mainfrom
collision-mesh-area-setters
Oct 16, 2026
Merged

zfergus merged 3 commits into
mainfrom
collision-mesh-area-setters

Conversation

@zfergus

@zfergus zfergus commented Oct 13, 2026 •

Copy link
Copy Markdown
Member

Description

Adds setters for the vertex and edge areas of CollisionMesh, so users can supply their own quadrature weights (e.g., 2πR·ds for axisymmetric models) instead of the barycentric areas.

  • set_vertex_areas / set_edge_areas in C++; vertex_areas / edge_areas are now read/write properties in Python.
  • Setters validate the size and require finite, positive values.
  • NormalCollisions::build already reads weights from these areas when use_area_weighting is on, so the weights reach the collisions with no per-collision loop. They also survive the rebuild inside ogc.TrustRegion::update_if_needed, and merged vertex-vertex terms stay exact.
  • Documents the average_mass / mean(weight) adjustment for initial_barrier_stiffness with weighted collisions. Adaptive stiffness was designed for unweighted collisions; with area weighting and a physical barrier, κ is a material parameter in Young's-modulus units.

API changes

  • New: CollisionMesh::set_vertex_areas(VectorXd) and CollisionMesh::set_edge_areas(VectorXd).
  • Python: mesh.vertex_areas = ... and mesh.edge_areas = ... now work. The getters still return read-only views, so mesh.vertex_areas *= f and mesh.vertex_areas[i] = x raise. Use mesh.vertex_areas = f * mesh.vertex_areas.
  • Backward compatible: default areas are unchanged.

Limitations

  • Custom areas do not support shape derivatives. The setters throw if init_area_jacobians() already ran, and init_area_jacobians() throws once custom areas are set. This avoids silently inconsistent gradients.
  • Collisions built before the setter call keep their old weights.

Fixes #266

Type of change

  • New feature (non-breaking change which adds functionality)
  • This change requires a documentation update

How Has This Been Tested?

  • Catch2 [areas]: scaled areas give scaled collision weights; invalid input is rejected; the Jacobian guard throws in both orders
  • nose2 python/tests/test_collision_mesh.py: same behavior through the bindings, plus read-only getter

Test Configuration:

  • OS and Version: macOS (Darwin 25.6.0)
  • Compiler and Version: AppleClang 21.0, Debug (C++ tests), Release (Python)

Checklist

  • I have followed the project style guide
  • My code follows the clang-format style guidelines of this project
  • I have performed a self-review of my code
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings
  • I have added tests that prove my fix is effective or that my feature works
  • New and existing unit tests pass locally with my changes
  • Any dependent changes have been merged and published in downstream modules

- Add set_vertex_areas/set_edge_areas (and Python property setters)
- Reject bad sizes and non-finite or non-positive areas
- Make custom areas and area Jacobians mutually exclusive
- Document weighted use of initial_barrier_stiffness

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@codecov

codecov Bot commented Oct 13, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 96.93%. Comparing base (f67f4ca) to head (8ef9135).

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #273      +/-   ##
==========================================
- Coverage   96.93%   96.93%   -0.01%     
==========================================
  Files         194      194              
  Lines       17349    17377      +28     
  Branches      944      948       +4     
==========================================
+ Hits        16817    16844      +27     
- Misses        532      533       +1     
Flag Coverage Δ
unittests 96.93% <100.00%> (-0.01%) ⬇️

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.

@chemiskyy

Copy link
Copy Markdown

Thanks a lot for the quick answer. I have tried it on our axisymmetric setup: macOS arm64, Python 3.13, built from source with pip. It works.

Setters

  • mesh.vertex_areas = ... / mesh.edge_areas = ... work, and the size, negative and non-finite checks raise as documented.
  • mesh.vertex_areas *= 2 raises, as documented.

Weights

  • With vertex_areas = 2*pi*R * vertex_areas and use_area_weighting + IMPROVED_MAX_APPROX, the edge-vertex weights are bitwise identical to our (built as a temporary workaround) per-collision Python loop, and the potential matches exactly.
  • On a merged vertex-vertex term, the setter gives 68.4855 against 68.4861 for our loop with a mean radius. That small gap is the one expected, and the setter value is the exact one.
  • After ogc.TrustRegion.update_if_needed, the weights are kept.

One request: allow zero areas. The setters require strictly positive values. In an axisymmetric model, the edges lying on the symmetry axis (r = 0) have zero ring area, and so does a vertex whose only edges lie on the axis. These primitives can legitimately sit in the collision mesh, e.g. a full solid of revolution whose extracted boundary includes the axis segment. Their zero weight is exactly what we want. Would accepting >= 0 (finite and non-negative) be possible? For now we can work around it with a tiny positive floor.

Version. The branch reports ipctk.__version__ == "2.0.0". Is #273 planned for 2.0 only, or also for a 1.6.x release? Either way, we will keep the loop as a fallback when the setters are unavailable.

On initial_barrier_stiffness: thanks for the explanation and the documentation. With area weighting, we will look at the physical barrier with κ set relative to Young's modulus rather than the adaptive range.

@zfergus zfergus closed this Oct 15, 2026
@zfergus
zfergus deleted the collision-mesh-area-setters branch October 15, 2026 14:59
@zfergus
zfergus restored the collision-mesh-area-setters branch October 15, 2026 14:59
@zfergus zfergus reopened this Oct 15, 2026
zfergus and others added 2 commits October 15, 2026 12:29
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Axisymmetric primitives on the symmetry axis have no ring area, and
their zero weight is the correct result. Zero-weight collisions are
dropped when the collisions are built, so they exert no contact force.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@zfergus

zfergus commented Oct 15, 2026

Copy link
Copy Markdown
Member Author

Thanks for testing this so thoroughly, and for the exact comparison against your loop.

Zero areas: done in 8ef9135. The setters now accept finite, non-negative values; negative, NaN and infinite values are still rejected. Collisions whose weight is zero are dropped when the collision set is built, so primitives on the symmetry axis contribute no force and cost nothing. You shouldn't need the positive floor anymore.

Version: main is 2.0.0, but this change is additive and backward compatible, so I'm happy to release it as v1.6.1 by cherry-picking it onto a 1.6.x branch. I'll follow up here once that exists. Keeping your Python loop as a fallback for older versions is the right call in the meantime.

@zfergus zfergus added the enhancement New feature or request label Oct 15, 2026
@zfergus zfergus added this to the v1.6.1 milestone Oct 15, 2026
@chemiskyy

Copy link
Copy Markdown

That is perfect thank you very much!

Best regards,
Yves

@zfergus
zfergus merged commit 4b3059c into main Oct 16, 2026
22 checks passed
@zfergus
zfergus deleted the collision-mesh-area-setters branch October 16, 2026 14:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

# Allow user-provided vertex/edge areas in CollisionMesh (e.g. for axisymmetric models)

2 participants