A Python-based tool to solve the Rural Postman Problem (RPP) on OpenStreetMap (OSM) data. It identifies a set of required edges (for example, residential streets) and calculates an Eulerian circuit that covers all of them with minimum total cost, exporting the result as a GPX file.
- Graph loading and filtering: imports OSM data using
osmnx/networkx, filters out non-driveable edges (e.g., footways, cycleways, private access), and keeps the largest connected component. - Required-edge selection: required service streets include
residential,living_street,tertiary, andunclassified. - Undirected and directed solvers:
- Undirected solver connects required components and fixes odd-degree nodes via min-weight matching.
- Directed solver respects one-way restrictions for both routing and required arcs, balancing in/out degree with min-cost flow.
- Directed preflight + diagnostics: validates required nodes against the drive graph, checks strongly connected components, and can emit a DRPP diagnostics report or a GPX file of blocking required edges.
- GPX export: generates a GPX route with edge geometry for navigation.
- Geometry-preserving edge selection: prefers OSM edges with geometry when building the Eulerian multigraph to avoid straight-line fallbacks.
Run the main script to process the sample data:
python main.pypython main.py --osm data/area.osm--osm: path to an.osmfile (defaults todata/area.osm).--ignore-oneway: treats one-way streets as bidirectional for shortest-path routing.--directed-service: uses the directed service graph and the directed solver for required arcs, fully respecting one-way restrictions.--drpp-diagnostics: writes a DRPP diagnostics report (SCC sizes, required nodes/edges outside the largest SCC, and cross-SCC required edges).--drop-drpp-blockers: removes required edges that fall outside the largest SCC before solving the directed problem.--drpp-blockers-gpx: writes blocking required edges to a GPX file (useful for inspection before dropping them).
The solver writes rpp_route.gpx in the current directory.
Run the unit tests with:
pytest