Skip to content

Commit e5e80e7

Browse files
committed
docs: describe Nav2 observation demo
Signed-off-by: SamuelFoo <fooenzesamuel@gmail.com>
1 parent 1fa278f commit e5e80e7

3 files changed

Lines changed: 85 additions & 10 deletions

File tree

discourse/3-layered-global-occupancy-map.md

Lines changed: 60 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,9 @@
22

33
# Layered Global Map Observations
44

5-
This post describes the observation interface for contributing temporary map
6-
information to the next generation Open-RMF prototype.
5+
This post describes the implemented observation interface and demos for
6+
contributing temporary map information to the next generation Open-RMF
7+
prototype.
78

89
The goal is to let robots and perception systems publish what they currently
910
observe without tying them to a specific central map implementation. The first
@@ -19,15 +20,21 @@ observations, can be added later.
1920
same sensor snapshot
2021
* Clear-space patches have TTLs, just like obstacle patches
2122
* A source can reset its previous observations without using a TTL
22-
* Robot-mounted sources can include the robot pose at observation time
23+
* Robot-mounted sources include the observation-frame pose at observation time
24+
* The Rust map server composes a static occupancy grid and active observations
25+
into `/map`
26+
* The Nav2 demo converts scans from three robots into point regions and displays
27+
the combined map
2328
* The observation messages live in `rmf_layered_map_msgs`, leaving
2429
`rmf_prototype_msgs` unchanged
2530

26-
# Observation Topic
31+
# Observation Topics
2732

28-
Observation sources publish dynamic map observations on:
33+
The layered map server uses these topics:
2934

35+
* `/map/static` - static `nav_msgs/OccupancyGrid`
3036
* `/map/region_updates` - [`MapRegionUpdate.msg`](../rmf_layered_map_msgs/msg/MapRegionUpdate.msg)
37+
* `/map` - composed `nav_msgs/OccupancyGrid`
3138

3239
The topic is an event stream. Updates are not latched because expired
3340
observations should not be replayed to a restarted map service as if they were
@@ -105,6 +112,47 @@ sensor-local regions with their sensor pose, while synthetic sources whose
105112
regions are already global can use the identity pose. The first implementation
106113
accepts point and axis-aligned rectangle regions.
107114

115+
# Layered Map Server
116+
117+
`rmf_layered_map_server` keeps the static occupancy grid separate from dynamic
118+
observations and publishes their composition on `/map`. It validates source
119+
timestamps and frames, ignores updates that are older than the latest accepted
120+
update from the same source, supports source resets, and removes observations
121+
after their TTL expires.
122+
123+
The server applies clear patches before obstacle patches from the same update.
124+
During composition, obstacle observations win over clear observations so
125+
occupied space is not accidentally erased by another active source.
126+
127+
# Three-Robot Nav2 Demo
128+
129+
The launch file starts three stationary robots in different free corners of the
130+
warehouse and spawns one deterministic Gazebo box near each robot. Each
131+
observation node subscribes to its robot's local `sensor_msgs/LaserScan`,
132+
filters invalid or out-of-range returns, and publishes the remaining scan
133+
endpoints as point regions.
134+
135+
Each scan is a replacement snapshot: `reset_source` removes the source's
136+
preceding points before the new points are added, and a short TTL removes the
137+
source if it stops publishing. The observation-frame pose is recorded in the
138+
shared `map` frame so the map server can transform the scan-local regions before
139+
rasterizing them.
140+
141+
The demo launches Nav2 localization but does not launch Nav2 planning or control
142+
components, RMF planning, or navigation goals. Three robot-local RViz windows
143+
are enabled by default, and another RViz window displays the combined global
144+
`/map`.
145+
146+
The scan-to-region conversion is deliberately simple so its information loss
147+
and publication cost are visible. `beam_stride` reduces the number of point
148+
regions, `publish_period_sec` throttles replacement snapshots, and
149+
`max_observation_range` limits represented returns. `ttl_sec` controls how
150+
quickly stale snapshots expire. Each publisher logs its number of input beams
151+
and output regions so message density, update rate, and visual fidelity can be
152+
compared. The current demo publishes occupied endpoints only; it does not
153+
convert raycast clearing into free-space regions or compress adjacent points
154+
into larger regions.
155+
108156
# Example Flow
109157

110158
A local costmap or LiDAR observation node can publish a replacement snapshot by:
@@ -118,22 +166,24 @@ A local costmap or LiDAR observation node can publish a replacement snapshot by:
118166
5. Giving each patch a TTL long enough to survive normal publication jitter but
119167
short enough to decay when the observation is no longer refreshed.
120168

121-
The map service should ignore snapshots from a source if their timestamp is
122-
older than a newer snapshot that has already been accepted. This prevents a late
123-
clear/reset message from removing obstacle information that came from a newer
169+
The map server ignores snapshots from a source if their timestamp is older than
170+
a newer snapshot that has already been accepted. This prevents a late clear or
171+
reset message from removing obstacle information that came from a newer
124172
observation.
125173

126174
# Implemented Test Coverage
127175

128-
The first server tests cover:
176+
The committed server and demo tests cover:
129177

130178
* composing obstacle regions over a static planning grid
131179
* point regions with non-zero map origins and non-1.0 resolutions
132180
* transforming robot-local regions into the global map frame
133181
* out-of-bounds regions, malformed point arrays, and unsupported region types
134-
* rejecting updates without a timestamp
182+
* rejecting updates without a timestamp or in a different global frame
135183
* pruning expired observations by TTL
136184
* clear and obstacle patches in the same update
137185
* late older snapshots being ignored
138186
* reset updates removing observations from the same source and map
139187
* multiple robot sources being stitched into one composed grid
188+
* filtering invalid and out-of-range laser returns
189+
* preserving original beam angles when scan points are sampled

map_server/README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,5 @@ ros2 launch rmf_layered_map_server_demo demo.launch.py
1111
```
1212

1313
Use `use_rviz:=False` for a headless run.
14+
15+
See [`rmf_layered_map_server_demo/README.md`](rmf_layered_map_server_demo/README.md) for the three-robot Nav2 observation demo.
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# Layered Map Server Demos
2+
3+
This package contains two demonstrations of the layered map server.
4+
5+
## TTL Smoke Test
6+
7+
This demo publishes a synthetic static grid and a temporary rectangle with a five-second TTL:
8+
9+
```bash
10+
ros2 launch rmf_layered_map_server_demo demo.launch.py
11+
```
12+
13+
## Three-Robot Nav2 Observation Demo
14+
15+
This demo combines laser observations from three stationary Nav2 robots in the global `/map`:
16+
17+
```bash
18+
ros2 launch rmf_layered_map_server_demo nav2_observations.launch.py
19+
```
20+
21+
Use `use_nav2_rviz:=False` to open only the combined-map view. Use `spawn_clutter:=False` to run against the unmodified warehouse world.
22+
23+
See [`3-layered-global-occupancy-map.md`](../../discourse/3-layered-global-occupancy-map.md) for implementation details, tuning arguments, and current limitations.

0 commit comments

Comments
 (0)