Skip to content

Conversation

Copy link

Copilot AI commented Nov 28, 2025

  • Understand the codebase structure and existing schema
  • Update tmap-schema.yaml to formally support flexible properties for nodes and edges
  • Update template_edge.yaml to include optional properties field
  • Add documentation for the properties system (doc/PROPERTIES.md)
  • Validate schema changes with existing test maps
  • Add namespace guidance for structuring properties by functional area
  • Add validate_map.py script for schema validation
  • Run code review and security checks

Summary

This PR implements a flexible properties system for topological maps:

  1. Schema Extension: Adds formal properties field definitions for both nodes and edges
  2. Template Update: Adds empty properties field to edge template for discoverability
  3. Documentation: Comprehensive guide including:
    • Property types and naming conventions
    • Namespace guidance for grouping properties by functional area (e.g., fleet_management, logistics, safety)
    • Code examples for accessing namespaced properties
  4. Validation Script: validate_map.py to validate map files against the schema

Example Namespaced Properties

properties:
  navigation:
    xy_goal_tolerance: 0.3
    yaw_goal_tolerance: 0.1
  fleet_management:
    capacity: 2
    priority_zone: true
  logistics:
    pickup_point: false

Validation Usage

ros2 run topological_navigation validate_map.py my_map.tmap2.yaml -v

Backwards compatible—existing maps without properties remain valid.

Original prompt

This section details on the original issue you should resolve

<issue_title>[FEAT]: Flexible Node and Edge Properties System</issue_title>
<issue_description>### Description

This feature request proposes extending the topological map schema to support arbitrary properties dictionaries for both nodes and edges, enabling flexible, application-specific metadata without requiring schema modifications.

Motivation

The current topological map structure has a fixed properties field in nodes (currently containing xy_goal_tolerance and yaw_goal_tolerance), but lacks extensibility for domain-specific applications. Different robotic applications require varied metadata that shouldn't necessitate core schema changes.

Proposed Feature

Add flexible properties dictionaries (represented as YAML maps) to both nodes and edges in the topological map schema.

Node Properties Examples

  • row: Identifies which row a node belongs to (e.g., in agricultural polytunnel scenarios)
  • semantics: Describes the semantic meaning of a node (e.g., "charging_station", "inspection_point", "rest_area")
  • zone: Operational zone designation
  • access_level: Permission level required for access
  • capacity: Maximum number of robots that can occupy the node simultaneously

Edge Properties Examples

  • max_speed: Maximum traversal speed for safety or operational constraints (m/s)
  • priority: Preference weight for path planning (higher values indicate more preferred routes)
  • width: Physical width of the traversable path (m)
  • surface_type: Terrain classification (e.g., "concrete", "grass", "gravel")
  • bidirectional: Boolean indicating if edge is bidirectional
  • weather_restrictions: Conditions under which edge should not be used

Design Requirements

  1. Backwards Compatibility: The properties field must be optional. Existing maps without properties should remain valid.
  2. Flexible Schema: Support arbitrary key-value pairs without requiring schema updates for new property types.
  3. YAML Map Format: Properties should be represented as YAML dictionaries for readability and ease of editing.
  4. Type Flexibility: Support various data types (strings, numbers, booleans, lists) as property values.

Schema Extension

The schema should be extended as follows:

For nodes (at nodes[].node.properties):

properties:
  type: object
  additionalProperties: true
  description: "Flexible dictionary of application-specific node properties"

For edges (at nodes[].node.edges[].properties):

properties:
  type: object
  additionalProperties: true
  description: "Flexible dictionary of application-specific edge properties"

Example Usage

nodes:
- meta:
    map: riseholme
    node: ChargingStation1
    pointset: riseholme
  node:
    name: ChargingStation1
    parent_frame: map
    pose: # ... pose details
    properties:
      xy_goal_tolerance: 0.3
      yaw_goal_tolerance: 0.1
      semantics: "charging_station"
      row: 3
      zone: "A"
      capacity: 2
    edges:
    - edge_id: ChargingStation1_WayPoint2
      node: WayPoint2
      properties:
        max_speed: 0.5
        priority: 10
        surface_type: "concrete"
        bidirectional: true
      # ... other edge fields

Implementation Considerations

  1. The schema file at config/tmap-schema.yaml needs to be updated to include the properties definitions.
  2. Validation should ensure properties is a dictionary but not enforce specific keys.
  3. Navigation and planning components should safely handle missing or unexpected properties.
  4. Documentation should provide guidance on common property conventions while allowing application-specific extensions.

Related Issues

This feature builds upon the topological map structure discussion in #203.

Additional Context

The example map at network.tmap2.yaml already demonstrates node properties in use. This feature request formalises and extends this capability to edges whilst ensuring schema consistency and backwards compatibility.

Benefits

  • Extensibility: Applications can add custom metadata without modifying core code
  • Semantic Richness: Enable rich semantic annotations for improved decision-making
  • Application Specialisation: Support domain-specific requirements (agriculture, warehousing, hospitals, etc.)
  • Planning Enhancement: Enable property-aware path planning (speed limits, priorities, restrictions)
  • Backwards Compatibility: Existing maps continue to work without modification</issue_description>

<agent_instructions>Make a start with this issue. Keep the changes as minimal as possible and ensure b...


💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.

Co-authored-by: marc-hanheide <1153084+marc-hanheide@users.noreply.github.com>
@marc-hanheide
Copy link
Member

@Iranaphor @ibrahimhroob @arsh09 please take a look at this minimally invasive proposal to properly allow properties to be represented in topological maps. This should allow us to represent semantic meaning and application specific constraints.

Copilot AI changed the title [WIP] Add flexible properties for nodes and edges in topological map Add flexible properties system for nodes and edges Nov 28, 2025
Copilot AI requested a review from marc-hanheide November 28, 2025 18:43
@marc-hanheide
Copy link
Member

@copilot expand the documentation by suggesting the use of name spaces for properties, to structure them more clearly. Typically, we want to separate different classes of properties through namespaces, i.e., a dictionary of properties may relate to “fleet_management” functionality, or it may only be used in specific applications like “logistics”. In this case, the suggested structure should be that properties are nested under a respective namespace. This doesn’t require special implementation treatment, but expanding the documentation.

As part of the implementation add a simple Python script to the “topological_navigation” package that can validate map yams files against the schema.

Co-authored-by: marc-hanheide <1153084+marc-hanheide@users.noreply.github.com>
Copy link
Author

Copilot AI commented Nov 28, 2025

@copilot expand the documentation by suggesting the use of name spaces for properties, to structure them more clearly. Typically, we want to separate different classes of properties through namespaces...

Added in b86eea4:

  1. Namespace documentation - The PROPERTIES.md now includes guidance on using namespaces to structure properties by functional area (e.g., fleet_management, logistics, safety, navigation). Examples show both flat and namespaced property structures.

  2. Validation script - Added validate_map.py that validates map YAML files against the schema:

    ros2 run topological_navigation validate_map.py my_map.tmap2.yaml -v

    The script checks schema compliance, warns about duplicate node names, and detects edges pointing to non-existent nodes.

@marc-hanheide marc-hanheide marked this pull request as ready for review November 28, 2025 19:02
Added a guideline for using package names as namespaces in properties.
@Iranaphor
Copy link
Contributor

Iranaphor commented Nov 29, 2025

I argue that the purpose of the topological map is to define a unified collection of information, including package name to what needs that information is not particularly important and associating information to current projects would set a bad precedent (though I understand the motivation of placing them into groups for readibility). Groups such as navigation, doesnt really make sense given there are many properties through the tmap file which are also used by core navigation but not included under this properties group.

I believe it makes more sense to utilise a different tag (perhaps under meta) called semantics, which is focused exclusively on assigning such semantic labels, then perhaps include the same under each edge named semantics too. Then also include an additional tag to include space for physical restrictions which are less of a semantic label but still direcly relevant.

Under these we could then utilise aspects such as:

- restrictions:
    - capacity: total number of robots allowed at once (default: 1)
    - max_external_width: max width of robot to fit through the space (think polytunnel rows)
    - max_external_height: max height of robot to fit through the space (think door height)
    - min_internal_width: min cavity width to encompas robot (think polytunnel bed width)
    - min_internal_height: min cavity height to encompas robot (think polytunnel bed height)
    - access_level: access required to gain entry
    - ...
- semantics:
    - zone:
        - labels: ['warehouse', 'polytunnel', ...]
        - details: {'tunnel_id':4, 'row_id':5, 'column_idx':2}
    - features:
        - labels: ['charging_station', 'door', 'e-gate', 'wait_node', ...]
        - details: {'charger_ip': [], 'e-gate': []}
    - environmental:
        - labels: ['grass', concrete', 'stones']
        - details: {...}

Of the other properties you mention in the associated issue:

  • max_speed: is a navigational parameter and could be included on an edge navigational properties as an action_parameters tag to be sent thorugh the edge action manager (of which fail_policy, fluid_navigation, recovery bahaviours_config, and config could also be moved into this)
  • weather_restrictions: are very platform dependent, are you refering to steep slopes under rain being an issue, or low-lying areas where puddles could form?
  • priority: is not a case for the map file to hold, this is up to a mrpp routing manager to decide priorities
  • bidirectional: would be breaking change, and this information is already available through both nodes in a bidirictional-pairing referencing links to the oneother

@Iranaphor
Copy link
Contributor

Iranaphor commented Nov 29, 2025

As another idea too, (with regards to the schema), I believe it could be worth us redefining the topological_map message and utilising a workflow for automatic generation of the schema based on that msg, implementing the "optional" and "defaults" aspects as comments defined within the msg files directly as these will display when you run for instance ros2 interface show sensor_msgs/msg/LaserScan as below. This would keep the map validation system as a core ROS system too rather then us hand modifying a schema file and associated documentation.

# Single scan from a planar laser range-finder
#
# If you have another ranging device with different behavior (e.g. a sonar
# array), please find or create a different message, since applications
# will make fairly laser-specific assumptions about this data

std_msgs/Header header # timestamp in the header is the acquisition time of
	builtin_interfaces/Time stamp
		int32 sec
		uint32 nanosec
	string frame_id
                             # the first ray in the scan.
                             #
                             # in frame frame_id, angles are measured around
                             # the positive Z axis (counterclockwise, if Z is up)
                             # with zero angle being forward along the x axis

float32 angle_min            # start angle of the scan [rad]
float32 angle_max            # end angle of the scan [rad]
float32 angle_increment      # angular distance between measurements [rad]

float32 time_increment       # time between measurements [seconds] - if your scanner
                             # is moving, this will be used in interpolating position
                             # of 3d points
float32 scan_time            # time between scans [seconds]

float32 range_min            # minimum range value [m]
float32 range_max            # maximum range value [m]

float32[] ranges             # range data [m]
                             # (Note: values < range_min or > range_max should be discarded)
float32[] intensities        # intensity data [device-specific units].  If your
                             # device does not provide intensities, please leave
                             # the array empty.

Also should the docs which copilot is generating not be added instead to the wiki, with that upgraded instead?

@Iranaphor Iranaphor marked this pull request as draft November 29, 2025 14:21
@marc-hanheide
Copy link
Member

@copilot add a reference to topological_navigation/doc/PROPERTIES.md into the topological_navigation/README.md, describing the new property system very briefly. Also update the root level README.md to refer the user to the README.md files in the subdirectory, with a very brief summary of the purpose of each individual ros package.

@marc-hanheide marc-hanheide marked this pull request as ready for review December 16, 2025 12:05
Copilot stopped work on behalf of marc-hanheide due to an error December 16, 2025 12:05
@marc-hanheide
Copy link
Member

@copilot try again

Copilot stopped work on behalf of marc-hanheide due to an error December 16, 2025 12:08
@marc-hanheide
Copy link
Member

Re #216 (comment)

Thank you for this detailed feedback – these are good points that helped clarify the intent and flexibility of the properties system.

I've updated the documentation in PROPERTIES.md to make it clearer that the properties system already supports the organisational structure you're proposing. The key insight is that namespaces are organisational tools, not requirements, and can be organised by domain concept (like restrictions and semantics) rather than by package name. I agree, we want to avoid duplication of information.

Your proposed structure works perfectly, but under the properties key where we should NOT enforce that things are organised by package, but in general favour re-usable information, e.g.:

properties:
  restrictions:
    capacity: 1
    max_external_width: 0.8
    max_external_height: 1.5
    min_internal_width: 1.2
    min_internal_height: 2.0
    access_level: "operator"
  semantics:
    zone:
      labels: ['warehouse', 'polytunnel']
      details: {tunnel_id: 4, row_id: 5, column_idx: 2}
    features:
      labels: ['charging_station', 'door', 'wait_node']
      details: {charger_ip: '192.168.1.100'}
    environmental:
      labels: ['grass', 'concrete', 'stones']

@marc-hanheide
Copy link
Member

OK, this now includes also a check that the YAML schema is a valid schema, so I will merge this now into aoc.

@marc-hanheide marc-hanheide merged commit f4e7912 into aoc Dec 16, 2025
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants