{"id":25231665,"url":"https://github.com/michaelgrupp/maps","last_synced_at":"2025-04-09T07:09:41.286Z","repository":{"id":275494144,"uuid":"904441334","full_name":"MichaelGrupp/maps","owner":"MichaelGrupp","description":"Inspect, compare and align multiple grid maps in an intuitive \u0026 fast GUI","archived":false,"fork":false,"pushed_at":"2025-04-07T18:26:57.000Z","size":16709,"stargazers_count":53,"open_issues_count":1,"forks_count":6,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-04-07T19:26:01.150Z","etag":null,"topics":["egui","grid-map","map","mapping","maps","native","navigation","occupancy-grid-map","robotics","ros","ros2","rust","slam","wasm"],"latest_commit_sha":null,"homepage":"https://crates.io/crates/maps","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/MichaelGrupp.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-12-16T22:32:25.000Z","updated_at":"2025-04-07T18:26:58.000Z","dependencies_parsed_at":null,"dependency_job_id":"42f488e2-b5a1-490b-9373-6b08fc6ee811","html_url":"https://github.com/MichaelGrupp/maps","commit_stats":null,"previous_names":["michaelgrupp/maps"],"tags_count":12,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MichaelGrupp%2Fmaps","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MichaelGrupp%2Fmaps/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MichaelGrupp%2Fmaps/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MichaelGrupp%2Fmaps/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/MichaelGrupp","download_url":"https://codeload.github.com/MichaelGrupp/maps/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247715846,"owners_count":20984118,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["egui","grid-map","map","mapping","maps","native","navigation","occupancy-grid-map","robotics","ros","ros2","rust","slam","wasm"],"created_at":"2025-02-11T12:36:37.101Z","updated_at":"2025-04-09T07:09:41.280Z","avatar_url":"https://github.com/MichaelGrupp.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# maps\n\n**Inspect, compare and align multiple grid maps in an intuitive \u0026 fast GUI**\n\n| \u003cimg src=\"https://raw.githubusercontent.com/MichaelGrupp/maps/refs/heads/master/data/doc/screenshot_0.png\" width=\"250\" /\u003e  | \u003cimg src=\"https://raw.githubusercontent.com/MichaelGrupp/maps/refs/heads/master/data/doc/screenshot_1.png\" width=\"250\" /\u003e  | \u003cimg src=\"https://raw.githubusercontent.com/MichaelGrupp/maps/refs/heads/master/data/doc/screenshot_2.png\" width=\"250\" /\u003e |\n|---|---|---|\n\n`maps` is 100% Rust and compiles \u0026 runs natively (cross-platform) or as web assembly.\n\n\u003ctable border=\"0\"\u003e\n \u003ctr\u003e\n    \u003ctd\u003e 🖥️ \u003ccode\u003ecargo install maps\u003c/code\u003e \u003c/td\u003e\n    \u003ctd\u003e \u003ca href=\"https://michaelgrupp.github.io/maps/\" target=\"_blank\"\u003e🌍 web demo\u003c/a\u003e \u003c/td\u003e\n \u003c/tr\u003e\n\u003c/table\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e click to show \u003cb\u003edifferences\u003c/b\u003e \u003c/summary\u003e\n\n#### Performance\nThe native app is of course faster, but the wasm build comes pretty close in performance! Unless you use several large maps, the difference will be probably not noticeable.\n\n#### IO \u0026 Features\n\nFilesystem interaction is obviously limited in a sandboxed browser environment. File IO in the web build is handled via `\u003cinput\u003e` fields by the browser instead of an egui file dialog.\n\nApart from the things listed below, the wasm target offers exactly the same UI \u0026 features.\n\n***Differences in wasm:***\n\n* It's not possible to load only the YAML file of a map and get the corresponding image automatically, you need to pass both YAML and image file.\n* Saving \u0026 loading sessions is not supported.\n* (Auto)saving of options is not supported.\n* No command line interface obviously.\n\n| | Native | Web |\n|---|---|---|\n| Open maps | \u003cul\u003e \u003cli\u003e CLI: `maps map1.yaml map2.yaml` \u003c/li\u003e \u003cli\u003e GUI: select `map1.yaml` and `map2.yaml` using \"Load Maps\" button \u003c/li\u003e \u003c/ul\u003e | GUI: select `map1.yaml`, `map1.png`, `map2.yaml`, `map2.png` using \"Load Maps\" button |\n| Save [session](#session-files) | \"Save Session\" button | not supported |\n| Reload session | \u003cul\u003e \u003cli\u003e CLI: `maps -s session.toml` \u003c/li\u003e \u003cli\u003e GUI: select file using \"Load Session\" button | not supported |\n| Load/Save [poses](#pose-alignment) | supported | supported |\n| [Screenshots](#-screenshot) | supported | supported |\n\n\n#### Recommendation\n\n* For quick, sporadic tasks (e.g. viewing a map, taking a measurement etc), the web version is totally sufficient and doesn't require you to install anything.\n* For more complex tasks (e.g. alignment of multiple maps), the native app is better suited.\n\n**Note**: Both web \u0026 native run purely local in your OS or browser, no data is uploaded anywhere.\n\n\u003c/details\u003e\n\n## Audience\n\n`maps` can be useful for you if ...\n\n* ...you work on mobile robot SLAM or navigation.\n* ...your SLAM or navigation system supports exporting maps as 2D grid map images.\n* ...you want to quickly work with the map files, but other tools are either...\n  * ...better suited for live data streams (e.g. RViz, Rerun, Foxglove etc)\n  * ...not supporting grid coordinates (most image viewers)\n  * ...bloated, vendor-locked or unsuited for dev workflows (commercial fleet/layout tools)\n* ...you want to display in a shared coordinate system, take measurements etc.\n* ...you want to align multiple, potentially very large maps.\n\nThe features are best summarized in a video:\n\nhttps://github.com/user-attachments/assets/391e8e02-77da-42ac-991d-02578a3cdaa0\n\n## Goals\n\nAt its core, `maps` is an image viewer that is aware of the metric properties of the grid maps.\n\n### Intuitive\n  * Maps of different resolutions can be displayed in a shared coordinate system with correct scale and position.\n  * Details of large maps can be quickly inspected using a lens tool without zooming \u0026 dragging.\n  * Several keybindings make it fast to use, e.g. `W A S D` for moving and `Q E` for rotating.\n  * Files can be loaded both via GUI and CLI.\n  * Sessions can be saved and loaded at a later point to continue working, settings are autosaved by default.\n  * No context menus or other hidden UI.\n\n### Fast\n  * Interaction should be fast and responsive, also with very large high resolution maps.\n  * maps is optimized to allow dragging / rotating images also at high zoom levels in real-time, with efficient resource usage.\n  * Built with [Rust](https://www.rust-lang.org/) using [egui](https://github.com/emilk/egui) + [wgpu](https://github.com/gfx-rs/wgpu).\n\n## Input\n\nThe supported grid map file format is ROS map_server files, i.e. a pair of image and metadata per map:\n\n* YAML metadata file containing information about the origin, resolution and other properties.\n* Image file containing the grid cells.\n\nSee the [ROS documentation](http://wiki.ros.org/map_server#Map_format) for all details.\n\n\u003e 💡 `maps` does not require a ROS installation, it just uses this data format as convention.\n\n## User Interface\n\n### Menu \u0026 Settings\n\n* Click `☰` to open the sidebar to manage maps and their visibility.\n* Click `⚙` to open the sidebar for settings.\n* Click the ℹ️ button in the lower right corner to display version \u0026 keybindings.\n\n### Views\n\n`maps` provides three different main view modes.\n\n\u003cimg src=\"https://raw.githubusercontent.com/MichaelGrupp/maps/refs/heads/master/data/doc/view_selection.png\" width=\"150\" /\u003e\n\n* `Aligned`:\n  * Maps are shown in a metric grid, with their origin at zero.\n  * The grid can be dragged and zoomed, grid lines can be shown etc.\n* `Tiles`:\n  * Map images are shown in separate tab tiles.\n  * The tab tiles can be freely rearranged, for example to view images side by side.\n* `Stacked`: Map images are shown stacked in a scrollable view.\n\n### Measurements\n\n\u003cimg src=\"https://raw.githubusercontent.com/MichaelGrupp/maps/refs/heads/master/data/doc/tool_measure.png\" width=\"125\" /\u003e\n\nDoes exactly what you think: activate the tool and click two points in the aligned grid view to measure their distance.\n\n### Lens\n\n\u003cimg src=\"https://raw.githubusercontent.com/MichaelGrupp/maps/refs/heads/master/data/doc/tool_hover_lens.png\" width=\"125\" /\u003e\n\nThe lens tool magnifies a region below the mouse cursor with a magnification factor (in Aligned view) or to the original image size (in Tiles / Stacked view). This makes it fast to inspect details of large maps in selected regions without tedious zooming and/or dragging.\n\n* Right-click the mouse on a map to enable/disable the lens (or press L).\n* Adjust it...\n  * in Aligned view: use the options side bar to set the magnification factor.\n  * in Tiles/Stacked view: scroll to adjust the size of the lens.\n\n### Fixed Lens\n\n\u003cimg src=\"https://raw.githubusercontent.com/MichaelGrupp/maps/refs/heads/master/data/doc/tool_fixed_lens.png\" width=\"125\" /\u003e\n\nIn the Aligned view, you can add multiple lenses that are looking at a fixed coordinate each. They stay centered at the coordinate that was clicked, even if the main grid is moved.\n\nThis can be useful when aligning large maps, where you need to watch different areas in detail to check how well they fit while moving the map.\n\n### Pose Alignment\n\nYou can change the pose of a map relative to the global origin in the aligned grid view.\n\nThis can be used when you have multiple maps with different origins (e.g. different floors, different origin due to remapping),\nor to align with a fixed layout, etc.\n\n* Select the map that you want to move in the menu sidebar.\n* Enter values or move the map with the keyboard (after enabling \"Move Map\")\n* Poses can be exported to YAML files.\n* Optionally, use the tools to make alignment easier, for example:\n   * make the texture of the maps transparent/colored using the blend settings\n   * add fixed lenses in different areas of a large map\n   * adjust the movement step size for the WASD/QE keybindings to the sensitivity you need\n\n\u003cimg src=\"https://raw.githubusercontent.com/MichaelGrupp/maps/refs/heads/master/data/doc/alignment.gif\" height=\"150\" /\u003e\n\n\u003e 👉 maps doesn't touch the `origin` of your `map.yaml` file, but writes a separate file.\n\u003e Many ROS tools don't support rotations in the map yaml file, and it's anyway cleaner to separate the alignment pose from the map origin.\n\n### Draw order\n\nAlso with transparency enabled, you might want to reorder the map layers.\n\nChanging the draw order is just a matter of using drag \u0026 drop in the map list of the menu panel:\n\nhttps://github.com/user-attachments/assets/0d68e18b-2980-4ffa-bf93-470fe7a9612d\n\n### Value interpretation \u0026 colormap à la ROS\n\nYou can display maps the same way as you would see them in RViz when using an occupancy grid publisher like map_server together with RViz.\n\n`maps` simulates this by first applying a [value interpretation](http://wiki.ros.org/map_server#Value_Interpretation) followed by a colormap.\nJust enable value interpretation and choose the options you want.\nThis allows for example to tune the free/occupied thresholds for your application, since `maps` directly shows the effect when the corresponding slider is moved.\n\n\u003cimg width=\"500\" alt=\"value_interpretation_examples\" src=\"https://github.com/user-attachments/assets/a5882a4d-0a06-4bdb-8bf8-ebc32041ea26\" /\u003e\n\u003cimg width=\"250\" alt=\"value_interpretation_ui\" src=\"https://github.com/user-attachments/assets/738843eb-9d15-4906-8a5b-eb273e5805e4\" /\u003e\n\n\u003e 💡 If the map metadata YAML already contains the optional `mode` parameter, value interpretation is enabled automatically for that map.\n\n\u003e 💩 The implementation in map_server is not fully consistent with the documentation.\n\u003e This is a \"standard\" that most likely will stay, but worth to consider that there are slight differences in case you rely on the documentation.\n\u003e Hence `maps` defaults to a reimplementation of that map_server quirk, but an implementation that follows the Wiki docs / occupancy grid message definition can be chosen as alternative.\n\n### 📸 Screenshot\n\n`maps` has a built-in screenshot feature.\n\n* Press `p` to save a picture of the full application.\n* Press `shift + p` to save a picture containing only the central panel that shows the maps.\n\n### Session files\n\nYou can save your session and reload it later using the menu. maps also asks you if you want to save before quitting or when there are unsaved changes.\n\nNote that `maps` never overwrites your input map files.\n\n\u003e ⚠️ The files that are written are not self-contained. They just contain the relevant config and point to the map file paths.\n\n### Configuration files\n\n#### Autosave\n\nThe general options are autosaved by default.\nSo for example, if you change the grid color and spacing, you will automatically have the same setting the next time you open maps.\n\nIf you don't want this, you can disable this for the active session in the options side bar of the app.\nAll options can be reset with the respective reset buttons in the UI.\n\n#### Custom\n\nIf you want to use a custom configuration file path instead of the autosaved default for a session:\n\n```\nmaps --config my_custom_config.toml\n```\n\nIf the file doesn't exist yet, it opens `maps` with default options, creates the file and saves your changes there on exit.\nYou can then reload these settings again anytime you want using the same command.\n\n## Install\n\nFirst, you need to [install the Rust toolchain](https://www.rust-lang.org/tools/install) if you don't have it already.\n\nThen you can install the latest release from [crates.io](https://crates.io/):\n\n```\ncargo install maps\n```\n\n---\n\nYou can also build completely from source if you want.\n\u003cdetails\u003e\n\u003csummary\u003eDetails\u003c/summary\u003e\n\n### Native build\n\nClone this repository, then:\n```bash\ncargo install --path maps/\n```\n\n(or `cargo build --release` if you just want to build)\n\n### Web assembly build\n\nYou can use [trunk](https://trunkrs.dev/) to directly build \u0026 serve the wasm version of `maps` from source. Just run:\n\n```\ntrunk serve --release\n```\nand go to: http://localhost:8080/index.html/#dev\n\n\nA `dist/` target folder for a specific URL can be generated with:\n\n```\ntrunk build --release --public-url \u003curl\u003e\n```\n\n\u003c/details\u003e\n\n## Run\n\nStart the app with:\n\n```bash\nmaps\n```\nUse the `Load Maps` button to add your map files.\n\n\nYou can also already pass map file paths from the command line:\n\n```bash\nmaps some/map.yaml some/other/map.yaml\n```\n\nSee `maps --help` for all command line options.\n\n## Development / Testing\n\nCI pipelines run for Linux, macOS, Windows and wasm targets:  \n[![Rust](https://github.com/MichaelGrupp/maps/actions/workflows/rust.yml/badge.svg)](https://github.com/MichaelGrupp/maps/actions/workflows/rust.yml) \n\nThere are integration tests in the `tests/` directory that are run in pull requests.\nThese include kit tests that check if the UI stays consistent, using the snapshot diff feature of `egui_kittest`.\n\n\u003cdetails\u003e\n\u003csummary\u003eHow to run locally\u003c/summary\u003e\n\nFirst, install [Git LFS](https://docs.github.com/en/repositories/working-with-files/managing-large-files/installing-git-large-file-storage) and `git lfs pull`.\nThe snapshot image blobs are versioned with it instead of normal Git.\n\nRun with snapshot diff check enabled (default feature `kittest_snapshots` of this crate):\n```\nRUST_LOG=maps=info cargo test --profile kittest --verbose -- --show-output\n```\n\nTo update the baseline snapshots (e.g. when changing the UI intentionally as part of the UI), set the `UPDATE_SNAPSHOTS=1` environment variable before the test command.\n\nRun without snapshot checks:\n```\nRUST_LOG=maps=info cargo test --profile kittest --verbose --no-default-features -- --show-output\n```\n\n\u003c/details\u003e\n\n`maps` has only a small public library. But in case you are interested: https://docs.rs/maps/latest/maps/\n\n---\n\nWith `-log-level debug` or `trace`, a debug window can be opened through a ⚒️ button in the footer panel.\n\n\u003cimg src=\"https://raw.githubusercontent.com/MichaelGrupp/maps/refs/heads/master/data/doc/debug_button.png\" width=\"125\" /\u003e\n\n## License\n\nApache 2.0\n\n\u003cdetails\u003e\n  \u003csummary\u003e\n    Cite\n  \u003c/summary\u003e\n  \u003cp\u003e\nIf you want to cite this repository, you can either use a footnote linking \u003ccode\u003ehttps://github.com/MichaelGrupp/maps\u003c/code\u003e or:\n  \u003c/p\u003e\n\n\u003cpre\u003e\u003ccode\u003e@misc{grupp2025maps,\n  title={maps: Inspect, compare and align multiple grid maps in an intuitive \u0026 fast GUI.},\n  author={Grupp, Michael},\n  howpublished={\\url{https://github.com/MichaelGrupp/maps}},\n  year={2025}\n}\u003c/code\u003e\u003c/pre\u003e\n\n\u003c/details\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmichaelgrupp%2Fmaps","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmichaelgrupp%2Fmaps","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmichaelgrupp%2Fmaps/lists"}