Ngoren/occupancy gridcells fix - #3536
Merged
remibettan merged 6 commits intoJul 16, 2026
Merged
Conversation
…ting, FOV masking and max-range clipping - Switch occupancy publisher from nav_msgs/GridCells to nav_msgs/OccupancyGrid - Cell semantics: 0=free, 100=occupied, -1=unknown (was all-zero before) - FOV masking: cells outside horizontal FOV cone (from depth camera fx) → -1 - True angular raycasting via θ=atan2(y,x) instead of fixed-Y column scan - Shadow propagation: free until first obstacle, unknown behind it per ray - Gap-ray fix: obstacle shadow spread across full angular footprint to prevent rays slipping through gaps between adjacent occupied cells - occupancy_max_range param (default 2.5m): cells beyond range → -1
…uard, cast and perf cleanups
|
Can one of the admins verify this patch? |
nivgo
marked this pull request as draft
July 8, 2026 14:00
nivgo
marked this pull request as ready for review
July 8, 2026 14:01
nivgo
force-pushed
the
ngoren/occupancy-gridcells-fix
branch
from
July 12, 2026 06:29
c32fcb6 to
cf63cdc
Compare
Gilaadb
approved these changes
Jul 14, 2026
Collaborator
|
@remibettan please help reviewing this PR, I also suggest running it |
remibettan
reviewed
Jul 16, 2026
- Center the grid about the camera axis with float cols/2 in both origin.y and the per-cell y: the integer division shifted odd-column grids (D585S emits 85 cols) half a cell laterally. Verified live: origin.y now -2.975 and the grid aligns with the point cloud. - Reject depth intrinsics with zero width, which would otherwise publish a silent all-unknown grid. - Stop the row scan at occupancy_max_range instead of skipping rows. - Drop the unreachable bin < 0 guard, document why it cannot trigger. - Rename bin_range to fov_span: it is the total FOV window, not the width of one bin. - Document occupancy_max_range in the README next to clip_distance.
remibettan
self-requested a review
July 16, 2026 11:34
remibettan
approved these changes
Jul 16, 2026
remibettan
merged commit Jul 16, 2026
94b995b
into
realsenseai:ros2-development
11 of 12 checks passed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Occupancy Grid — How It Works
1. Overall Pipeline
flowchart TD FW["🔲 D585S Firmware\npacked bitmask — 1 bit per cell\n(1=occupied, 0=not occupied)"] subgraph fn["publishOccupancyFrame()"] INIT["Init every cell → -1\n(unknown)"] FOV{"FOV cone check\n|y| ≥ x · tan(hfov/2) ?"} RANGE{"Max range check\nx > occupancy_max_range ?"} BIN["Assign to angular bin\nθ = atan2(y, x)"] RAY["Scan ray nearest → farthest\nwith per-bin occlusion state"] OCC{"Occupied\nbit set?"} SHAD{"Ray already\noccluded?"} SPREAD["Spread shadow to\n± n_spread neighbour bins\nn_spread = ceil(cell_size·N_bins / 2·x·bin_range)"] end FREE["0\nconfirmed free"] OB["100\noccupied"] UNK["-1\nunknown"] OUT["📦 nav_msgs/OccupancyGrid"] FW --> INIT --> FOV FOV -->|outside camera FOV| UNK FOV -->|inside FOV| RANGE RANGE -->|beyond 2.5 m default| UNK RANGE -->|within range| BIN --> RAY --> OCC OCC -->|yes| OB --> SPREAD OCC -->|no| SHAD SHAD -->|yes| UNK SHAD -->|no| FREE SPREAD -->|"neighbours → -1"| UNK FREE --> OUT OB --> OUT UNK --> OUT2. Cell Value Semantics
flowchart LR subgraph legend["Cell value in OccupancyGrid.data[]"] direction TB A["0\n✅ confirmed free\nRay passed through — no obstacle seen"] B["100\n🔴 occupied\nFirmware bit = 1"] C["-1\n❓ unknown\nOutside FOV, beyond max range,\nor shadowed behind an obstacle"] end3. Live Output
Real grid published by the driver, shown in rviz with the live point cloud overlaid.
White = free (
0), gray = unknown (-1), occupied cells (100) sit under the detected boxes —note the FOV wedge, the shadows fanning out behind each obstacle, and the unknown
region beyond
occupancy_max_range:4. Column-Based vs True Angular Raycasting
5. Shadow Propagation Along a Ray
6. Gap-Ray Fix (Shadow Spreading)
Without the fix, a ray can slip through the gap between two adjacent occupied cells
that fall in different angular bins:
7. FOV Masking
8. Coordinate Mapping: Firmware → OccupancyGrid