Skip to content

This PlatformIO library provides a OpenStreetMap (OSM) map fetching and caching system for ESP32-based devices.

License

Notifications You must be signed in to change notification settings

CelliesProjects/OpenStreetMap-esp32

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

OpenStreetMap-esp32

License Release Issues PlatformIO Codacy Badge

This PlatformIO library provides a OpenStreetMap (OSM) map fetching and tile caching system for ESP32-based devices.
Under the hood it uses LovyanGFX and PNGdec to do the heavy lifting.

map

A map is composed from downloaded OSM tiles and returned as a LGFX sprite.
Tile fetching and decoding is performed concurrently across both cores on dualcore ESP32 devices.
A composed map can be pushed to the screen, saved to SD or used for further composing.
Downloaded tiles are cached in psram for reuse.

This should work on any ESP32 type with psram and a LovyanGFX compatible display.
OSM tiles are quite large at 128kB or insane large at 512kB per tile, so psram is required.

Multiple tile formats and providers are supported

You can switch provider and tile format at runtime, or set up a different default tile provider if you want.
This library can do it all and is very easy to configure and use.

How to use

This library is PlatformIO only due to use of modern C++ features. The Arduino IDE is not supported.
Use the latest Arduino ESP32 Core version from pioarduino to compile this library.

See the example PIO settings and example code to get started.

Example platformio.ini settings

These settings use Arduino Release v3.2.0 based on ESP-IDF v5.4.1 from pioarduino.

[env]
platform = https://github.com/pioarduino/platform-espressif32/releases/download/53.03.20/platform-espressif32.zip
framework = arduino

lib_deps =
    celliesprojects/OpenStreetMap-esp32@^1.1.0
    lovyan03/LovyanGFX@^1.2.7
    bitbank2/PNGdec@^1.1.3

Functions

Get the minimum zoom level

int getMinZoom()

Get the maximum zoom level

int getMaxZoom()

Set map size

void setSize(uint16_t w, uint16_t h)
  • If no size is set a 320px by 240px map will be returned.
  • The tile cache might need resizing if the size is increased.

Get the number of tiles needed to cache a map

uint16_t tilesNeeded(uint16_t w, uint16_t h)

This returns the number of tiles required to cache the given map size.

Resize the tiles cache

bool resizeTilesCache(uint16_t numberOfTiles)
  • The cache content is cleared before resizing.
  • Each 256px tile allocates 128kB psram.
  • Each 512px tile allocates 512kB psram.

Don't over-allocate
When resizing the cache, keep in mind that the map sprite also uses psram.
The PNG decoders -~50kB for each core- also live in psram.
Use the above tilesNeeded function to calculate a safe and sane cache size if you change the map size.

Fetch a map

bool fetchMap(LGFX_Sprite &map, double longitude, double latitude, uint8_t zoom)
  • Overflowing longitude are wrapped and normalized to +-180°.
  • Overflowing latitude are clamped to +-90°.
  • Valid range for the zoom level is from getMinZoom() to getMaxZoom().

Free the psram memory used by the tile cache

void freeTilesCache()
  • Does not free the PNG decoder(s).

Switch to a different tile provider

bool setTileProvider(int index)

This function will switch to tile provider index defined in src/TileProvider.hpp.

  • Returns true and clears the cache on success.
  • Returns false -and the current tile provider is unchanged- if no provider at the index is defined.

Get the number of defined providers

OSM_TILEPROVIDERS gives the number of defined providers.

Example use:

const int numberOfProviders = OSM_TILEPROVIDERS;

Note: In the default setup there is only one provider defined.

See src/TileProvider.hpp for example setups for https://www.thunderforest.com/ that only require an API key and commenting/uncommenting 2 lines.

Registration and a hobby tier are available for free.

Adding tile providers

Other providers should work if a new definition is created in src/TileProvider.hpp.
Check out the existing templates to see how this works.

If you encounter a problem or want to request support for a new provider, please check the issue tracker for existing reports or open an issue.

Get the provider name

char *getProviderName()

Example code

Example returning the default 320x240 map

#include <Arduino.h>
#include <WiFi.h>

#define LGFX_M5STACK_CORE2  // for supported devices see 
                            // https://github.com/lovyan03/LovyanGFX

#include <LGFX_AUTODETECT.hpp>
#include <LovyanGFX.hpp>

#include <OpenStreetMap-esp32.hpp>

const char *ssid = "xxx";
const char *password = "xxx";

LGFX display;
OpenStreetMap osm;

double longitude = 5.9;
double latitude = 51.5;
int zoom = 5;

void setup()
{
    Serial.begin(115200);
    Serial.printf("WiFi connecting to %s\n", ssid);

    WiFi.begin(ssid, password);
    while (WiFi.status() != WL_CONNECTED)
    {
        delay(10);
        Serial.print(".");
    }

    Serial.println("\nWiFi connected");

    display.begin();
    display.setRotation(1);
    display.setBrightness(110);

    // create a sprite to store the map
    LGFX_Sprite map(&display); 

    // returned map is 320px by 240px by default
    const bool success = osm.fetchMap(map, longitude, latitude, zoom);

    if (success)
        map.pushSprite(0, 0);
    else
        Serial.println("Failed to fetch map.");
}

void loop()
{
    delay(1000);
}

Example setting map resolution and cache size on RGB panel devices

#include <Arduino.h>
#include <WiFi.h>
#include <LovyanGFX.hpp>

#include "LGFX_ESP32_8048S050C.hpp" // replace with your panel config

#include <OpenStreetMap-esp32.hpp>

const char *ssid = "xxx";
const char *password = "xxx";

LGFX display;
OpenStreetMap osm;

int mapWidth = 480;
int mapHeight = 800;
int cacheSize = 20; // cache size in tiles where each osm tile is 128kB
double longitude = 5.9;
double latitude = 51.5;
int zoom = 5;

void setup()
{
    Serial.begin(115200);
    Serial.printf("WiFi connecting to %s\n", ssid);

    WiFi.begin(ssid, password);
    while (WiFi.status() != WL_CONNECTED)
    {
        delay(10);
        Serial.print(".");
    }

    Serial.println("\nWiFi connected");

    display.begin();
    display.setRotation(1);
    display.setBrightness(110);

    osm.resizeTilesCache(cacheSize);
    osm.setSize(mapWidth, mapHeight);

    LGFX_Sprite map(&display);

    const bool success = osm.fetchMap(map, longitude, latitude, zoom);
    if (success)
    {
        // Draw a crosshair on the map
        map.drawLine(0, map.height() / 2, map.width(), map.height() / 2, 0);
        map.drawLine(map.width() / 2, 0, map.width() / 2, map.height(), 0);

        map.pushSprite(0, 0);
    }
    else
        Serial.println("Failed to fetch map.");
}

void loop()
{
    delay(1000);
}

License differences between this library and the map data

This library has a MIT license

The OpenstreetMap-esp32 library -this library- is licensed under the MIT license.

The downloaded tile data has a ODbL license

OpenStreetMap® is open data, licensed under the Open Data Commons Open Database License (ODbL) by the OpenStreetMap Foundation (OSMF).

Use of any OSMF provided service is governed by the OSMF Terms of Use.