ZERO Notificatons

NO Feedback yet!!

okay

xparo
X.P.A.R.O



project - ROS Map Editor



Two numbers in every ROS map's YAML file have consequences far beyond the map itself. The resolution decides how much memory the costmaps use, how fast the planner runs and how precisely the robot can thread a doorway. The origin decides where the map sits in the world, and therefore where every saved goal, dock and zone ends up. This guide explains how to choose both and how to change them safely.

What resolution means

resolution is the size of one map cell in metres. 0.05, the default in slam_toolbox and the most common choice, means 5 cm squares. The number of cells grows with the square of the resolution:

ResolutionCells for a 50 m × 50 m buildingRobot 0.5 m wide spansTypical use
0.10 m500 × 500 = 250,0005 cellsLarge warehouses, outdoor areas, slow planners on small computers
0.05 m1000 × 1000 = 1,000,00010 cellsMost indoor robots
0.025 m2000 × 2000 = 4,000,00020 cellsSmall robots in tight spaces, precise docking areas

Halving the cell size quadruples the cell count. The global costmap normally matches the map, and it holds several layers of those cells, so memory use and the time spent updating layers and planning grow roughly in proportion. On a laptop this rarely matters; on a Raspberry Pi running Nav2 on a large site, it is the difference between a planner that answers instantly and one that takes seconds.

How fine is fine enough?

Resolution has to be good enough to tell open space from obstacles at the scale of your tightest squeeze. Rounding to cells can cost up to about one cell of clearance on each side of a gap, and the costmap's inflation is also counted in cells. A useful rule: make the cell size no more than about a tenth of the smallest clearance you care about. A robot that must pass through 80 cm doorways with 15 cm to spare on each side is comfortable at 5 cm and tight at 10 cm.

Finer is not automatically better. A 2D laser's range noise is typically a few centimetres, so very fine maps record noise as detail and fill up with speckles, and AMCL does more work per scan for little gain. Match the resolution to your sensor and your robot, not to the screen.

The origin

origin: [x, y, yaw] is the pose of the map's lower-left corner in the map frame. SLAM tools choose it so that the robot's starting position is at (0, 0), which means the origin is usually a pair of negative numbers. Two facts follow:

  • Changing the origin moves the whole map in the world frame. Every goal, waypoint, docking pose and keep-out zone expressed in map coordinates now points somewhere else. Do it only deliberately, and update everything that depends on it.
  • Keep the yaw at 0. Many ROS tools ignore the yaw in the origin. If the map needs rotating, rotate the image itself, or simply give the robot its initial pose with the correct heading.

Good reasons to set the origin by hand: making the map frame line up with a building's coordinate system, so that positions from floor plans can be used directly, or placing (0, 0) at the charging dock, which makes the dock pose trivial to configure. If you do, also make every mask used by Nav2's costmap filters use the same origin and resolution.

Changing the resolution of an existing map

Re-mapping at the new resolution gives the best result, but you can also downsample a map you already have. The catch is that ordinary image resizing averages pixels, so one-pixel walls fade into grey that the map server reads as unknown or free. The safe way is to give each block the darkest pixel in it, so any obstacle survives. This script halves (or quarters) a map's resolution that way:

"""Downsample a ROS map without losing thin walls. Needs numpy, Pillow, PyYAML."""
import sys

import numpy as np
import yaml
from PIL import Image

src_yaml, dst_name, factor = sys.argv[1], sys.argv[2], int(sys.argv[3])

meta = yaml.safe_load(open(src_yaml))
img = np.array(Image.open(meta['image']))   # run it from the map's folder
h, w = img.shape
h2, w2 = h // factor, w // factor
# drop rows at the top and columns at the right that don't fill a whole
# block, so the lower-left corner (the origin) stays where it was
img = img[h - h2 * factor:, :w2 * factor]
small = img.reshape(h2, factor, w2, factor).min(axis=(1, 3)).astype(np.uint8)

Image.fromarray(small).save(dst_name + '.pgm')
meta['image'] = dst_name + '.pgm'
meta['resolution'] = meta['resolution'] * factor
with open(dst_name + '.yaml', 'w') as f:
    yaml.safe_dump(meta, f, default_flow_style=None, sort_keys=False)

Run it as python3 downsample_map.py depot.yaml depot_10cm 2. On Nav2's depot map it turned 604 × 307 pixels at 5 cm into 302 × 153 pixels at 10 cm with the origin unchanged, and every obstacle pixel of the original fell inside an obstacle pixel of the result. Because the darkest value wins, unknown also beats free in mixed blocks, which is the conservative choice. Check the result in the ROS Map Editor before using it.

Going the other way, to a finer resolution, does not add information. If you need more detail, map again with a smaller resolution in slam_toolbox's parameters, as described in mapping with slam_toolbox.

Summary

  • Start at 5 cm. Go coarser for very large sites or slow computers, finer only for tight spaces and precise docking.
  • Keep the cell size well below your smallest important clearance.
  • Treat the origin as part of your robot's configuration: change it only on purpose, keep the yaw at 0, and keep masks in step.
  • When downsampling, keep the darkest pixel, never the average.

More guides

Oct. 4, 2026, 10:11 a.m.
Mapping with slam_toolbox in ROS 2: From First Scan to Saved Map
Read more..
Oct. 4, 2026, 10:12 a.m.
Keep-Out Zones and Speed Limits in Nav2 with Costmap Filters
Read more..
Oct. 4, 2026, 10:13 a.m.
How to Clean Up a SLAM Map: Noise, Ghost Obstacles and Glass Walls
Read more..
Oct. 4, 2026, 10:14 a.m.
ROS Map Files Explained: The .pgm Image and .yaml Metadata
Read more..

If you have any query or problem
feel free to contact us
email: [email protected]