rviz_satellite: putting satellite tiles under a robot in RViz
Display internet satellite imagery in RViz
At a glance
- What is it?
- rviz_satellite is an RViz plugin for ROS 2 that renders map tiles at the position published on a sensor_msgs/msg/NavSatFix topic, so a ground robot can be seen against the aerial imagery of the area it is driving in. It is a display tool rather than a mapping tool, and it needs a tile server URL that you supply yourself, with no default configured.
- Who is it for?
- rviz_satellite fits a ROS 2 developer debugging a GPS-based robot who wants to see the vehicle against real aerial imagery in RViz, especially a team whose robots have no internet access and can serve tiles from a local directory. It does not fit a workflow that needs a map to be produced rather than displayed, and it does not fit a pipeline that needs vector tiles, since the plugin follows the OpenStreetMap raster tile convention only.
- Can I use it commercially?
- Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 161 days ago.
- What is it written in?
- Mainly C++, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
A display plugin anchored to a NavSatFix message
rviz_satellite is described as an RViz plugin for displaying satellite maps at the position of a sensor_msgs/msg/NavSatFix message. That description sets the scope precisely. It is not a mapping package and it does not produce a map from sensor data. It takes a position that something else already knows, the GPS fix your robot publishes, and draws the corresponding aerial imagery underneath the other geometry in your RViz view. The problem it solves is a debugging one: when a robot is behaving oddly, seeing the vehicle on real streets rather than on a blank grid tells you things a costmap cannot. The audience is a ROS 2 developer with a GPS-equipped ground robot, and the project is Apache-2.0 licensed with the default branch on main. There is a ROS 1 version on a separate branch, which the README notes for anyone arriving from the older stack.
Adding an AerialMap display and pointing it at a topic
The integration is a display in your RViz configuration, and the usage instructions take two sentences. You add an instance of AerialMap to your RViz config and point it to a sensor_msgs/msg/NavSatFix topic. That is the entire contract. There is no separate node to launch, no service to call and no topic to subscribe to beyond the fix itself, because the plugin is a display that subscribes to the position and renders in the 3D view. A demo in the repository makes the result visible in one command, which runs a launch file that makes RViz circle around a geo point you define.
ros2 launch rviz_satellite demo.launch.xmlThe demo directory holds the launch file, the RViz configuration and a publish_demo_data script, and the README shows the resulting view, with the coordinates given as 48.211486, 16.383982 in Vienna using OpenStreetMap tiles. That circling motion is the reason this plugin is useful in practice, since a static map tells you where the robot is once, and a moving one shows you the track it took and how it lines up with the roads.
The tile URL is your job, and the format is fixed
The plugin does not come with any preconfigured tile URL, and that is stated plainly in the README. You must provide a tile URL, described as an Object URI, from which the satellite images are loaded, and the URL should have the form http://server.tld/{z}/{x}/{y}.jpg, where the tokens {z}, {x} and {y} represent the zoom level, the x coordinate and the y coordinate respectively. Those tokens are substituted automatically by rviz_satellite when it makes the HTTP requests. The README lists candidate servers, with OpenStreetMap at https://tile.openstreetmap.org/{z}/{x}/{y}.png, TomTom at https://api.tomtom.com/map/1/tile/basic/main/{z}/{x}/{y}.png?tileSize=512&key=[TOKEN], and Mapbox at https://api.mapbox.com/styles/v1/mapbox/satellite-v9/tiles/256/{z}/{x}/{y}?access_token=[TOKEN]. For some of these you have to request an access token first, and the README asks you to refer to the respective terms of service and copyrights. The current implementation follows the OpenStreetMap convention for tile URLs, which the README notes implies that only raster tiles are supported, no vector tiles.
Local file tiles for robots with no network
Tiles can optionally be loaded from a local filesystem if they have been downloaded beforehand, for cases where robots do not have internet access. The example given is a file URI, file:///tmp/tile/{z}/{y}/{x}.jpg, which loads files from the /tmp/tile directory. Note the order of the tokens in that example differs from the HTTP form, with {y} before {x}, which is worth checking against the layout of the directory you actually populate. For a robot that has to work in a building, a mine or a field with no coverage, this is the option that makes the plugin usable at all, and it also removes the question of what the tile provider's terms of service require of an embedded device.
The cache is handled for you but not for your benefit. Map tiles are cached to $HOME/.cache/rviz_satellite, and the README is explicit that at present the cache does not expire automatically, so you should delete the files in the folder if you want the images to be reloaded. In practice that means a long-running session keeps serving whatever tiles it fetched first, which is invisible while the map is unchanged and confusing the moment the imagery is updated.
The display options, from transparency to fade-out
The option list is short and each entry has an obvious purpose. Topic is the topic of the GPS measurements. Alpha is the display transparency. Draw Below causes the map to be displayed below all other geometry, which is what you want in almost every case, since the map is a reference layer and the robot model should stay on top of it. Zoom is the zoom level of the map, with recommended values of 16 to 19, since anything smaller is very low resolution, and 22 as the current maximum. Blocks is the number of adjacent tiles in addition to the centre tile to load, with 8 as the maximum. Timeout specifies a timeout since the last received message timestamp, after which the map is faded out, and you can disable it by setting it to 0.
The timeout deserves a note. It is a liveness check tied to the message timestamps rather than to wall clock time, so if the GPS topic stops publishing, the map fades instead of leaving a stale image pinned at the last known position. That is a good default for a moving vehicle, since a stationary map at a stale position is actively misleading, and setting it to 0 turns the check off for a setup where the position topic is expected to be quiet.
Local maps for tile servers that cover one region
Some tile servers only cover a specific region rather than the whole world, and the Use Local Map option is how you work with them. The README explains the consequence: enabling it means the zoom levels and the tile coverage deviate from the standard scheme and need to be defined manually, and in particular the local origin is the top-left corner of the local map region. The options appear once the top-level Use Local Map option is unfolded. Meter per Pixel (Zoom 0) defines the length of a pixel edge in the image in metres at zoom level 0, with a default of 0.0. Origin CRS is the epsg code of the coordinate reference system of the local origin, which should be a cartesian coordinate system, and is not set by default. Origin X and Origin Y are the position of the local origin in the given CRS, both defaulting to 0.0.
The worked example in the README uses public orthographic photos provided by Geobasis NRW, which cover only a smaller part of western Germany at very high resolution, and the options are derived directly from that service's scheme.
* `Object URI: https://www.wmts.nrw.de/geobasis/wmts_nw_dop/tiles/nw_dop/EPSG_25832_16/{z}/{x}/{y}`
* `Meter per Pixel (Zoom 0): 4891.97`
* `Origin CRS: EPSG:25832`
* `Origin X: -46133.17`
* `Origin Y: 6301219.54`That is the price of a regional, high resolution source, four numbers you have to take from the provider's own metadata rather than derive yourself.
Where a raster tile plugin stops being enough
Two cases point elsewhere. The first is a workflow that needs a map as output rather than as a backdrop, which means a mapping or localisation stack that estimates the robot's pose and builds its own map; a display plugin that draws whatever tiles a public provider happens to serve cannot substitute for that, and the position it draws from is the input you already had. The second is a pipeline that needs vector tiles, richer styling, or offline rendering at a scale where downloading raster tiles over HTTP at runtime is the bottleneck. The README is explicit that the OpenStreetMap convention is what is supported, and that this implies only raster tiles, no vector tiles.
There is also a licensing dimension worth separating from the technical one. The plugin itself is Apache-2.0, but the imagery it displays comes from whoever serves the tiles, and the README asks you to check the terms of service and copyrights of the provider, with some of the listed servers requiring an access token first. An embedded device repeatedly hitting a hosted tile endpoint is a usage pattern that a free public tile server is unlikely to be happy about, which is another reason the local file option exists.
Finally, the scope is RViz and ROS 2 only. There is no web viewer, no Qt standalone application and no ROS 1 support on this branch, and the ROS 1 version lives on a separate branch, so a team on the older distribution has to make that choice deliberately.
Editorial conclusion
rviz_satellite fits a ROS 2 developer debugging a GPS-based robot who wants to see the vehicle against real aerial imagery in RViz, especially a team whose robots have no internet access and can serve tiles from a local directory. It does not fit a workflow that needs a map to be produced rather than displayed, and it does not fit a pipeline that needs vector tiles, since the plugin follows the OpenStreetMap raster tile convention only. Before you adopt it, pick a tile server and read its terms of service, because the README asks you to refer to the respective terms of service and copyrights and the plugin ships no preconfigured URL, and remember that the tile cache under $HOME/.cache/rviz_satellite does not expire on its own.
Frequently asked questions
What does rviz_satellite do?
It is an RViz plugin for displaying satellite maps at the position of a sensor_msgs/msg/NavSatFix message. You add an instance of AerialMap to your RViz config and point it at the topic publishing the GPS fix, and the plugin renders the corresponding tiles in the 3D view.
How do I try out rviz_satellite?
Run ros2 launch rviz_satellite demo.launch.xml, which makes RViz circle around a geo point you define. The demo directory in the repository holds the launch file, the RViz configuration and a publish_demo_data script, and the README shows the result at coordinates 48.211486, 16.383982 in Vienna with OpenStreetMap tiles.
Where do the map tiles come from in rviz_satellite?
You supply the tile URL yourself, since the plugin comes with no preconfigured one. The URL should have the form http://server.tld/{z}/{x}/{y}.jpg, and the README lists OpenStreetMap, TomTom and Mapbox examples, noting that some require an access token first and that you should refer to the respective terms of service and copyrights.
Can rviz_satellite work without an internet connection?
Yes. Tiles can optionally be loaded from a local filesystem if downloaded beforehand, for cases where robots do not have internet access, using a file URI such as file:///tmp/tile/{z}/{y}/{x}.jpg. Note that the cache in $HOME/.cache/rviz_satellite does not expire automatically, so you have to delete the files yourself if you want the images reloaded.
What are the main display options in rviz_satellite?
Topic for the GPS measurements, Alpha for transparency, Draw Below to place the map under all other geometry, Zoom for the map zoom level with 16 to 19 recommended and 22 as the current max, Blocks for the number of adjacent tiles up to 8, and Timeout for a fade-out after a given time since the last message timestamp, which you disable by setting it to 0.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/nobleo-rviz-satellite)Was this useful?