Skip to content

Route decomposed fields along headlands (Lyrical)#134

Open
u33549 wants to merge 3 commits into
open-navigation:lyricalfrom
u33549:Feature/umutc/f2c-enhancements-lyrical/route-decomp
Open

Route decomposed fields along headlands (Lyrical)#134
u33549 wants to merge 3 commits into
open-navigation:lyricalfrom
u33549:Feature/umutc/f2c-enhancements-lyrical/route-decomp

Conversation

@u33549

@u33549 u33549 commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

Summary

Ports #119 to the lyrical branch. Completes decomposition-with-route support:
routes decomposed (multi-cell) fields along their headlands so inter-cell
connections follow the shared headland, and fixes a multi-cell headland crash.
Builds on the lyrical ports of #112/#113/#117 (PRs #123, #126, #130).

Changes

Route decomposed fields along headlands

  • Previously a decomposed field applied the headland per sub-cell first, leaving
    each cell a disconnected island; per-cell TSP then stitched routes with
    straight-line bridges that cut across the field. Non-TSP modes flattened the
    multi-cell swaths into a single-cell orderer, fanning connections across the field.
  • Now: shrink the whole field to a travel ring, decompose it, then shrink each
    sub-cell again for the swath area. genRoute is fed the border-sharing travel
    cells so inter-cell connections follow the headlands.
  • generateRouteTSP takes separate travel_cells and swath_cells: small fields
    use a single global genRoute; large fields (swath count above a cap) fall back
    to per-cell TSP to avoid the O(N²) all-pairs OOM.
  • Non-TSP route modes combined with decomposition are rejected with a clear
    INVALID_MODE_SET error.
  • Decomposed cells and swaths are reused across the swath and TSP branches.

Make the global-route swath cap a parameter

  • default_max_swaths_for_global_route (default 300) replaces the hard-coded
    threshold, tunable at runtime via the dynamic-parameters callback.

Fix multi-cell headland crash on collapsed sub-cells

  • The multi-cell generateHeadlands(F2CCells) overload applied the headland to
    each sub-cell through the single-Field overload (ending in .getGeometry(0)).
    ConstHL is a negative buffer, so a sub-cell narrower than ~2×width collapses to
    empty and getGeometry(0) threw "Geometry does not contain point 0" on
    decomposed fields.
  • Buffer each sub-cell directly, skip cells that collapse to empty, add every
    resulting polygon (a negative buffer may split one cell into several), and throw
    a clear CoverageException if every sub-cell collapses. Generator/width
    resolution extracted into a shared resolveGenerator() helper.

Distro notes (lyrical)

No adaptation from #119 was needed — every touched file is byte-identical to the
rolling base, so the #119 delta applies verbatim. lyrical already uses the
nav2:: (nav2_ros_common) convention (declare_parameter_if_not_declared,
NodeThread) and test_server.cpp already includes <cmath> and <filesystem>.

u33549 added 3 commits July 17, 2026 00:52
A sub-cell narrower than ~2x the headland width collapsed to an empty
geometry under the inward buffer, and getGeometry(0) then threw instead
of being handled.

Buffer each sub-cell directly, skip empty results, and keep every
polygon a split may produce; throw a clear error only if every cell
collapses. Adds regression tests for both cases.
Decomposed fields applied the headland per sub-cell first, isolating
each cell; routes then bridged cells with straight lines cutting
across the field.

Shrink the field to a travel ring first, decompose that, then shrink
each sub-cell again for its swaths, so connections follow the shared
headland instead. TSP planning uses a single global genRoute for small
fields and falls back to per-cell TSP above a swath-count cap, avoiding
an all-pairs OOM. Non-TSP route modes are rejected with decomposition,
since they only support a single cell.
default_max_swaths_for_global_route replaces the hard-coded threshold, with a note
on when to tune it; drop the redundant show_log argument comments.
Copilot AI review requested due to automatic review settings July 16, 2026 21:54

Copilot AI 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.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

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.

2 participants