Repository navigation
1.0.0
Added
- Interactive viewer: way splitting, node deletion, and node position drag editing
- Interactive viewer: nodes can be inserted into OSM ways by dragging the blue midpoint handles between existing nodes in Edit mode
- Interactive viewer: barrier ways can now be split (✂️ button on nodes), matching the existing road and footway split behaviour; closed barriers are excluded
- Interactive viewer: vertex-level editing for manual annotations in Edit mode
- Interactive viewer: tag editing with save and undo support
- Interactive viewer: audit change log stored in
.annotations.json - Interactive viewer: feature search by ID or name in the sidebar; search now also matches all OSM tag values and, for annotations, the annotation type and all extra property keys and values (e.g. searching "wall" or "barrier" finds matching annotations)
- Interactive viewer: category and subtype visibility toggles
- Interactive viewer: Leaflet.Snap integration for precise annotation alignment
- Interactive viewer: GPX file import for waypoint overlays
- Interactive viewer: GPX upload modal with map name input (previously a stub)
- Interactive viewer: drag-and-drop
.mapdatafile upload;/api/upload_mapdatavalidates viaMapData.loadand saves to the data directory with collision-safe naming - Interactive viewer: Tracker mode for live robot position via ROS2
- Interactive viewer: planner mode can download and parse OSM data on demand
- Interactive viewer: planning parameters (
grid_margin,obstacle_radius,buffer_widths,grid_cost_weight) configurable in all three map creation dialogs (fetch area, GPX upload, planner fetch) via collapsible advanced-options panels; server defaults populate fields on load - Path planning module (
pathsolver) with A* graph search and cost-grid support - Path planning: annotated paths take priority over obstacle cells
- Path planning: paths-only planning mode (constrained to mapped ways)
- Path planning: cancellable planning requests
- New planner config parameters in
planner_defaults.yaml:grid_cost_weight,obstacle_radius, and per-typebuffer_widths(road,footway,barrier) — previously hardcoded in source - OSM response caching: Overpass query results are persisted to a
.osm_cache.jsonsidecar file and reused on subsequent loads when the bounding box matches, avoiding redundant network requests - YAML waypoint format as an alternative to GPX
map_data_infoCLI tool to print statistics about a.mapdatafileosm_cloudlaunch file with configurable grid topic and static transform publishingosm_cloud: dynamic reconfigure support for runtime tuning ofmax_path_dist,neighbor_cost, andgrid_res- Documentation site (MkDocs Material)
- Dedicated
Testingdocumentation page (docs/dev/testing.md) with per-module design notes and guidance for adding new tests pyproject.tomlwith ruff configuration for code style enforcement, compatible with ROS2 builds- Type hints across core and utility modules
- pytest suite covering core logic and path planning edge cases
- Expanded test suite:
test_overpass.py(retry logic, rate limiting, status polling),test_errors.py(malformed GPX, corrupt files, Overpass timeouts, planning failures),test_parsing.py(OSM element classification and buffering),test_fill_grid.py(footway cost assignment, barrier cell marking),test_viewer_helpers.py(GeoJSON roundtrip, way splitting, change log migration),test_viewer_routes.py(annotation CRUD, path-traversal security, way operations), and extendedtest_integration.py(OSM cache roundtrip, bbox mismatch,parse_intersections)
Changed
- Interactive viewer: GPX download now exports a
<trk><trkseg><trkpt>track by default; a Track / Waypoints toggle in the planner panel switches back to the legacy<wpt>format - Interactive viewer: annotation vertex handles in Edit mode now only appear when the annotation is clicked, not for all annotations at once
- Interactive viewer: annotation vertex handles now use the same orange circle + midpoint style as OSM node editing, replacing Leaflet.draw square handles
- Interactive viewer: transparent overlay markers provide larger click/drag hit targets for OSM nodes, annotation vertices, and planner waypoints without changing their visual appearance
- Interactive viewer: node drag in Edit mode is more responsive
visualize_mapdataCLI tool removed; the browser-based viewer supersedes itgrid_cost_weight,obstacle_radius, andbuffer_widthsare now per-run arguments togrid_astar,RRTStar, andReplanPath;osm_margin + reserve_marginreplaced with a singlegrid_marginconstant (150 m default) accepted as a per-call override inMapData.__init__,parse_osm_nodes, andseparate_waysMapData.get_points()now vectorizes UTM conversion by passing full lat/lon arrays toutm.from_latlonin one call instead of looping per node; all nodes are projected into the map's zone for consistencyRRTStarnow supports Informed RRT* sampling (informed=True, default): once an initial path is found, random samples are drawn from an ellipsoidal subset defined by the current best cost, accelerating convergence toward the optimumRRTStarnow supports adaptive neighbor radius (adaptive_radius=True, default): the rewiring radius shrinks asγ·√(log n / n)so the number of rewiring checks stays bounded while preserving asymptotic optimalitysmooth_pathnow returns the best collision-free intermediate state instead of reverting to the original path entirely when a smoothed segment collides with an obstacleReplanPathrefactored into focused sub-modules: grid construction moved toPathGrid(pathsolver/grid_constructor.py), path smoothing tosmooth_path(pathsolver/smoothing.py), and matplotlib debug visualization tovisualize_replan(pathsolver/visualizer.py)- Core architecture split into modular components:
OverpassClient,parsing,serialization - Config loading centralized to
map_data/utils/config.py, eliminating duplicated YAML-loading logic frommap_data.pyandreplan.py - Logging configuration centralized in
setup_logging()(map_data/utils/config.py);info.py,create_mapdata.py, andviewer/app.pynow call it insidemain()instead of invokinglogging.basicConfigat module level with inconsistent formats .mapdataserialisation migrated from pickle to JSON + WKT; legacy pickle support was subsequently removed for security reasons- Overpass queries parallelised for faster map data loading
Wayclass refactored to a@dataclasswith full type hintsos.pathreplaced withpathlib.Paththroughout the codebase- Code formatting standardized via ruff across all source modules
pyproject.tomlandsetup.pyaligned for ROS2 build compatibility
Fixed
-
visualizer.py: swapped X/Y axis labels corrected — Easting is now on the X axis, Northing on Y -
Interactive viewer: node drag in Edit mode missed clicks intermittently because canvas node markers rendered below the SVG ghost layer; node markers now use the SVG renderer so events reach them directly
-
Interactive viewer: adding a node to a buffered (Polygon) way drew a faint spike from the buffer outline back to the new node position because
apply_added_nodesinserted the centerline coordinate into the exterior ring of the buffer polygon; geometry is now left unchanged for Polygon ways and onlyway.nodesis updated -
Interactive viewer: split segments of buffered footways and barriers were rendered thinner than the original after a node had been added to the way; the spike inserted into the buffer polygon corrupted its area/perimeter, causing
split_wayto calculate a smaller-than-correct buffer radius -
Interactive viewer: splitting a way at a synthetic (user-added) node failed silently because
apply_added_nodeswas not called beforesplit_wayin the segments and node-list endpoints; synthetic nodes are now inserted into the way geometry and an extended nodes cache is built so the split resolves correctly -
Interactive viewer: added nodes did not appear anywhere in the sidebar; the
add_nodeevent is now written to the change log on creation and removed on undo, and added-node entries are shown in the Annotations panel with an undo button -
Interactive viewer: deleting one segment of a split way caused the entire original way to disappear on the next file reload; segment deletions are now stored under their virtual ID (
"<id>:<index>") so only the deleted segment is suppressed while the remaining segments survive -
Interactive viewer: reverting any annotation edit (tag override, node deletion, node move) on a way that had also been split left the stale pre-revert geometry on the map alongside the newly restored geometry until page reload;
_reloadWaynow always uses the segments endpoint so split virtual layers (id:n) are atomically replaced -
Interactive viewer: Closed roads and footways (e.g. roundabouts) were rendered as filled polygons instead of an annular ring:
buffer_linenow converts a closed-loopPolygonto aLineStringbefore buffering, unless the way carriesarea=yes -
Interactive viewer: tag change-log entries silently disappeared from the changes panel after any metadata refresh (
refreshMetadata/loadMapData) becausetagMapused numeric keys while the server'schange_logstores tag ids as strings; both call-sites now normalise to string keys -
Interactive viewer:
_reselectFeatureandfocusFeatureByIdnow compareString(_featureId) === String(wayId); previously strict equality failed to reselect real OSM ways (numeric_featureId) after a reload that converted the ID to a string, leaving the feature visually deselected -
Interactive viewer: duplicate
clicklisteners onway-edit-saveandway-edit-add-prop-btncaused double row insertion and double API calls on each action -
Interactive viewer: planner
mousemove/mouseuphandlers accumulated on the map with eachredraw()call; handlers are now tracked in_mapDragListenersand removed viamap.off()before each redraw -
Interactive viewer:
fetch_areaand OSM data parsing now run in a background thread; the route returns a task ID immediately and the client polls/api/fetch_area/<task_id>for completion, preventing UI hangs and WebSocket timeouts during long Overpass fetches -
Annotation deletion via the Del key in the viewer
-
Path traversal vulnerability in viewer API: user-supplied
fileparameter is now validated against the resolved data directory before any file access -
/api/fetch_areanow rejects requests wheremin_lat >= max_latormin_lon >= max_lon -
parse_yaml_filenow wraps all parse errors in a try/except and returns[]with a log message, matching the error contract ofparse_gpx_file -
Path planning with split ways
-
Thread-safe cancellation in the replanning module
-
create_mapdatanode: existing file load was missing the.mapdatasuffix, causingMapData.loadto receive an incorrect path -
create_mapdatanode:--downloadflag was passed as a positional argument toprocess_map_data, now correctly passed as a keyword argument -
Multi-zone UTM boundary warning when loaded area spans two UTM zones
-
route_plannerpreloads its map and caches oneGraphPlannerper map / way set / snap distance (plan_route(planner=...)); a request plans in milliseconds instead of rebuilding the graph. -
Planner screen: Robotour goal QR codes per waypoint (
/api/qr,map_data.utils.qr) shown full screen for the robot camera or downloaded as PNG. -
Goal QR codes are vector art (
/api/qr.svg,qr_svg): the caption used to be rasterised into the PNG, so it went blocky when the viewer scaled the code up to fill the screen. The modal now shows an SVG with the caption as HTML text beside it, and offers an SVG download for printing.
Pull requests
- Add planning mode by @vlk-jan in #2
- Improvements by @vlk-jan in #3
- Improvements by @vlk-jan in #4
- Tracker mode - online ROS2 robot tracking by @vlk-jan in #5
- Documentation by @vlk-jan in #6
- Progress on MISC and simple todo entries by @vlk-jan in #7
- Add more tests, specify formatting, minor bug fixes by @vlk-jan in #8
- Version 1.0.0 release by @vlk-jan in #9
Full Changelog: https://github.com/vras-robotour/map_data/commits/v1.0.0 · changelog