# Autonomous Warehouse AMR with ROS 2 Jazzy, Gazebo Harmonic and Nav2

**URL:** https://discourse.openrobotics.org/t/autonomous-warehouse-amr-with-ros-2-jazzy-gazebo-harmonic-and-nav2/57292
**Category:** Projects
**Tags:** ros2, gazebo
**Created:** [August 10, 2026, 5:03pm UTC](https://discourse.openrobotics.org/t/autonomous-warehouse-amr-with-ros-2-jazzy-gazebo-harmonic-and-nav2/57292 "2026-08-10T17:03:50Z")
**Posts on this page:** 4
**Page:** 1

<div class="post-metadata">

### Author: ![anastasios03git](https://sea2.discourse-cdn.com/flex022/user_avatar/discourse.openrobotics.org/anastasios03git/32/24472_2.png) [@anastasios03git](https://discourse.openrobotics.org/u/anastasios03git)
#### Post date: [August 10, 2026, 5:03pm UTC](https://discourse.openrobotics.org/t/autonomous-warehouse-amr-with-ros-2-jazzy-gazebo-harmonic-and-nav2/57292/1 "2026-08-10T17:03:50Z")

</div>

Hi everyone,

I’d like to share my first complete autonomous mobile robot project: an **Autonomous Warehouse AMR simulation** built with **ROS 2 Jazzy, Gazebo Harmonic and Nav2**.

The robot is a differential-drive AMR equipped with a simulated **2D GPU LiDAR** and can autonomously navigate inside a warehouse environment using:

- **AMCL** for localization
- **robot\_localization EKF** for odometry / TF
- **SmacPlanner2D** for global path planning
- **Regulated Pure Pursuit** for path tracking
- Local and global obstacle-aware costmaps
- **Nav2 Collision Monitor** for safety

I also built a small mission system where missions are defined in YAML files, for example:

`PICKUP → SHELFA → DROPOFF → HOME`

The mission manager supports retries, pause/resume, cancellation, status tracking and mission logging.

For testing dynamic obstacles, the simulation includes a moving warehouse worker. The robot detects the worker through LiDAR, updates the Nav2 costmaps and reacts accordingly.

I also created a simple **Tkinter operator dashboard** for selecting missions, monitoring mission progress, viewing the current/next station, elapsed time, event logs and Nav2 lifecycle status.

The complete system can be launched with a single ROS 2 launch command.

The project is available on GitHub:  
`https://github.com/Anastasios03git/autonomous-warehouse-amr`

I’d be very interested in feedback, especially regarding the ROS 2 / Nav2 architecture and ideas for improving the project further.

Thanks!

---

<div class="post-metadata">

### Author: ![sokstherobot](https://sea2.discourse-cdn.com/flex022/user_avatar/discourse.openrobotics.org/sokstherobot/32/34858_2.png) [@sokstherobot](https://discourse.openrobotics.org/u/sokstherobot)
#### Post date: [August 11, 2026, 4:22pm UTC](https://discourse.openrobotics.org/t/autonomous-warehouse-amr-with-ros-2-jazzy-gazebo-harmonic-and-nav2/57292/2 "2026-08-11T16:22:15Z")

</div>

Went through the repo, and the mission layer is more complete than most showcase projects: retries with costmap clears between attempts, pause implemented as cancel plus re-send with a refreshed stamp (the right way to do it, since Nav2 has no native pause), and a shared status topic driving both the dashboard and the CLI. Two small things I noticed while reading, offered as polish:

1. The mission manager resolves mission\_points.yaml, missions/, and mission\_logs/ from a hardcoded ~/warehouse\_ws path. Installing those with data\_files and resolving them through get\_package\_share\_directory, or exposing the paths as a ROS parameter, would let the same code run for anyone who clones into a differently named workspace. This kind of thing only ever bites the second user, which is why it is easy to miss as the first.
2. /mission\_status publishes only on state changes, so a dashboard started mid-mission sees nothing until the next transition. Publishing with transient\_local durability (and matching QoS on the subscriber) hands late joiners the last known state immediately. One line on each side, and the dashboard gets noticeably more robust.

Curious how the moving worker interacts with the Collision Monitor in practice: does it trigger actual stops and slowdowns in your runs, or does Nav2 usually replan around it before the monitor engages?

---

<div class="post-metadata">

### Author: ![anastasios03git](https://sea2.discourse-cdn.com/flex022/user_avatar/discourse.openrobotics.org/anastasios03git/32/24472_2.png) [@anastasios03git](https://discourse.openrobotics.org/u/anastasios03git)
#### Post date: [August 11, 2026, 9:34pm UTC](https://discourse.openrobotics.org/t/autonomous-warehouse-amr-with-ros-2-jazzy-gazebo-harmonic-and-nav2/57292/3 "2026-08-11T21:34:27Z")

</div>

Thanks a lot for going through the project in that much detail — both points are very useful.

I agree about the hardcoded `~/warehouse_ws` paths. The current version was originally built around my development workspace, so making mission resources package-relative with `get_package_share_directory()` or exposing them as ROS parameters would make the project much more portable.

The `transient_local` suggestion for `/mission_status` also makes sense. Right now the status is event-driven, so a dashboard joining mid-mission can indeed wait until the next transition before receiving anything. I’ll look at using matching transient-local QoS on both the mission manager and dashboard.

Regarding the moving worker: in my tests the LiDAR detects the worker and the robot reacts to it through the Nav2 obstacle pipeline. I’ve observed stopping / avoidance behavior, but I haven’t yet instrumented the run closely enough to say that every stop is specifically caused by Collision Monitor rather than the controller/costmap response occurring first. That would be a good next test — monitoring the Collision Monitor state and velocity commands while the worker crosses the path.

---

<div class="post-metadata">

### Author: ![sokstherobot](https://sea2.discourse-cdn.com/flex022/user_avatar/discourse.openrobotics.org/sokstherobot/32/34858_2.png) [@sokstherobot](https://discourse.openrobotics.org/u/sokstherobot)
#### Post date: [August 13, 2026, 2:46am UTC](https://discourse.openrobotics.org/t/autonomous-warehouse-amr-with-ros-2-jazzy-gazebo-harmonic-and-nav2/57292/4 "2026-08-13T02:46:08Z")

</div>

That was fast. Package-relative resources will make it clone-and-run for anyone, and transient\_local on the status topic is one of those small QoS details that makes a project feel production-shaped. Your Collision Monitor observation matches what I have seen elsewhere: with a slow obstacle the costmap replan usually wins the race, and the monitor earns its keep when something appears inside the lookahead faster than a control cycle. If you ever want to force it during testing, have the worker step out from behind a shelf at close range; occlusion is the thing that defeats the costmap path. Nice work again.
