AMCL never publishes map->odom transform (persistent “queue is full” for laser scans) — husarion_ugv_autonomy_ros, real Panther hardware
Environment
-
Robot: Husarion Panther, real hardware
-
Repo: husarion/husarion_ugv_autonomy_ros (ros2 branch, cloned fresh)
-
ROS 2 Jazzy
-
User Computer: running as a VMware Workstation Pro VM (Ubuntu 22.04.5), bridged network directly to the Panther’s switch (confirmed 0% packet loss, <1ms ping to 10.15.20.2)
-
LiDAR: RPLiDAR S3, connected via USB passthrough to the VM, with a custom scan_filter.py node that blanks out the rear 180° of the scan (robot chassis is in the way) and republishes on /scan_filtered
-
SLAM=False, using a pre-built, verified map (map_server loads it correctly: “Read map /maps/map.pgm: 963 X 587 map @ 0.05 m/cell”)
Symptom
AMCL activates normally (lifecycle: Configuring → Activating → “Setting pose (…): 0.000 0.000 0.000” → “Managed nodes are active”), but it never publishes the panther/map → panther/odom transform. The following repeats indefinitely, every ~2.5s, and never self-resolves:
[panther.amcl]: Message Filter dropping message: frame 'laser' at time X for reason 'discarding message because the queue is full'
[panther.global_costmap.global_costmap]: Timed out waiting for transform from panther/base_link to panther/map to become available, tf error: Invalid frame ID "panther/map" ... frame does not exist
[panther.global_costmap.global_costmap]: Failed to activate global_costmap because transform ... did not become available before timeout
[panther.lifecycle_manager_navigation]: Failed to bring up all requested nodes. Aborting bringup.
/panther/particlecloud is never published, confirming AMCL never successfully processes a single scan.
What I’ve confirmed working (individually, via direct tf2_echo / ros2 topic hz tests)
-
panther/base_link → laser (our static_transform_publisher): stable, correct values every time
-
panther/odom → panther/base_link (from ekf_filter): stable, correct values every time, ~50Hz
-
/scan_filtered: publishing at ~20-40Hz, correct frame_id (“laser”), sane range data (also tested with raw unfiltered /scan — same result)
-
global_frame_id/odom_frame_id/base_frame_id on amcl: correctly set to panther/map/panther/odom/panther/base_link
-
No duplicate nodes on the graph (checked ros2 node list for dupes)
-
use_sim_time on amcl: false (correct for real hardware)
-
Time is synced between the VM and the Panther’s onboard computer (checked actual message header.stamp values from both /scan_filtered and /panther/odometry/filtered — sub-300ms difference, not growing over time)
-
Only one publisher/subscriber pair on /scan_filtered, correctly matched QoS (we found and fixed an initial RELIABLE vs BEST_EFFORT mismatch between our filter node and amcl/costmap subscriptions — this did NOT fix the issue, but is a legitimate config error we corrected)
What I’ve tried, with no effect on the core issue
-
Increasing transform_tolerance to 2.0 for amcl, local_costmap, and global_costmap (baked into nav2_params.yaml before first activation, not just live param set)
-
Publishing an explicit /panther/initialpose (both zero and non-zero covariance) via ros2 topic pub
-
Full stack restarts (LiDAR, filter, static TF, and Nav2 all together, clean order)
-
Rebuilding the Docker image (docker compose build --no-cache) from a completely fresh git clone with minimal .env changes
-
Restarting the Panther’s onboard ROS driver container
-
Switching the VM’s virtual NIC from e1000 to vmxnet3 (better network stack, confirmed lower-level, direct route to the robot)
-
Fixing the QoS mismatch mentioned above
Question
Is there a known interaction in the husarion_ugv_autonomy_ros nav2_params.yaml template between AMCL’s laser message_filter and a custom/remapped scan topic (as opposed to the default sensor pipeline) that could cause this specific permanent “queue is full” deadlock? Or is there a recommended way to get debug-level logs specifically from the amcl node (RCUTILS_LOGGING_SEVERITY_THRESHOLD=DEBUG in docker/.env did not seem to produce additional amcl-specific output) so I can see what’s happening internally when it tries (and fails) to process a scan?
Happy to provide full logs, ros2 topic info --verbose dumps, or anything else needed to help diagnose this.