Skip to content

Replimap SDK & API

Developer Documentation and Usage Guide


Main Sections


1. Introduction

Replimap is a professional-grade HD map authoring, processing, and analysis platform designed to work with ASAM OpenDRIVE (XODR) maps. It provides comprehensive capabilities for creating, editing, validating, converting, and analyzing road networks at lane-level precision, supporting modern automotive, simulation, and mapping workflows.

The Replimap SDK exposes these capabilities as a native, in-process software development kit, while the Replimap API defines the stable, public interface through which applications interact with the underlying engine. Together, the SDK and API enable developers to integrate Replimap’s backend functionality directly into their own software stacks, without reliance on any specific user interface or rendering technology.

The SDK is designed to be: - Deterministic and robust
- Suitable for interactive and headless usage
- Safe for integration into long-running applications
- Independent of UI frameworks and visualization layers

All rendering, editor tooling, and user interaction logic are intentionally kept outside the SDK and are expected to be implemented by the integrating application.


Purpose of This Document

This document serves as a combined SDK and API reference, providing both conceptual guidance and detailed technical documentation. It is intended to help developers understand:

  • The overall scope and capabilities of Replimap
  • How the SDK and API are structured and organized
  • Which modules are available and how they relate to each other
  • How to use the API to create, modify, validate, convert, and analyze OpenDRIVE maps
  • How to work with long-running and asynchronous operations
  • Best practices for safe, efficient, and predictable usage

This document is designed to be suitable for both day-to-day development and long-term integration planning.


Intended Audience

This documentation is intended for software engineers, SDK integrators, and technical users who wish to embed Replimap functionality into their own applications or pipelines. Readers are expected to have familiarity with:

  • General software development concepts
  • Backend or SDK-based integration
  • Automotive mapping or simulation domains (recommended but not mandatory)

Prior knowledge of Replimap’s internal implementation is not required.


Scope and Non-Goals

The Replimap SDK and API focus exclusively on backend functionality, including data modeling, geometry processing, validation, and conversion. They do not include:

  • User interface components
  • Rendering or visualization systems
  • Editor widgets, tools, or interaction logic
  • Platform-specific UI frameworks

By keeping these concerns separate, the SDK ensures maximum flexibility, performance, and long-term maintainability across different client applications and environments.

2. Replimap SDK Capabilities Overview

Replimap provides a comprehensive set of backend capabilities for working with ASAM OpenDRIVE (XODR) maps across their entire lifecycle — from creation and editing, to validation, conversion, and deep inspection. The SDK and API are designed to support both interactive authoring tools and headless, automated workflows with the same level of precision and determinism.

At a high level, Replimap can be described as a lane-level road network engine with strong guarantees around structural correctness, geometric consistency, and repeatable results.


2.1 OpenDRIVE Map Authoring and Editing

The SDK exposes full programmatic control over OpenDRIVE map content, enabling applications to:

  • Create and manage complete road networks
  • Define and modify road plan-view geometry
  • Model elevation, superelevation, and lateral profiles
  • Create, edit, and organize lane sections and lanes
  • Control lane widths, borders, offsets, and heights
  • Define road connectivity and lane-level topology
  • Create and manage junctions and their internal connections

All editing operations are designed to be deterministic and explicitly controlled through the API, making them suitable for both manual authoring tools and automated generation pipelines.


2.2 Lane-Level Topology and Connectivity

Replimap operates on a detailed lane-based topology model, allowing precise control and inspection of:

  • Lane predecessor and successor relationships
  • Cross-road lane connectivity
  • Junction lane linking
  • Road and lane ordering and normalization
  • Connectivity graphs representing the navigable structure of the map

These capabilities enable advanced use cases such as routing analysis, consistency checks, and simulation-ready map preparation.


2.3 Roadside Objects, Signals, and Controllers

The SDK supports the creation and management of OpenDRIVE objects and traffic elements, including:

  • Roadside objects such as guardrails, barriers, poles, trees, buildings, and obstacles
  • Parametric and repeated objects
  • Signals with detailed positioning and orientation
  • Signal dependencies and validity ranges
  • Traffic signal controllers and phase definitions

All objects and signals can be positioned relative to roads or lanes, with full access to their attributes and relationships.


2.4 Geometry, Coordinate Systems, and Spatial Queries

Replimap provides extensive geometric and spatial utilities, including:

  • Support for multiple coordinate systems and geo-referencing
  • Conversion between road-relative (s, t) and Cartesian (x, y, z) coordinates
  • Sampling of road and lane geometry at arbitrary resolutions
  • Projection of points onto road reference lines
  • Queries for heading, curvature, elevation, and super-elevation
  • Spatial filtering and bounding-box queries

These features enable precise geometric analysis and integration with external geospatial data sources.


2.5 Import, Export, and Data Conversion

The SDK supports robust data exchange workflows, including:

  • Importing and exporting OpenDRIVE files
  • Version-aware OpenDRIVE serialization
  • Partial and subset-based export
  • Batch import and export workflows
  • Deterministic serialization suitable for automated pipelines

In addition to OpenDRIVE I/O, Replimap includes dedicated conversion capabilities through the HERE2ODR module (described later in this document).


2.6 HERE2ODR Conversion

The HERE2ODR module enables the creation of OpenDRIVE maps from HERE data sources. Supported workflows include:

  • Conversion of HERE tiles within a bounding box or GeoJSON polygon
  • Conversion based on explicit HERE tile identifiers
  • Processing of encoded HERE HD map data
  • Route-based conversion using HERE Routing APIs
  • Path-matching conversion, where only roads corresponding to a given path are converted

These workflows allow users to generate OpenDRIVE maps that are immediately ready for editing, validation, or simulation.


2.7 Validation and Quality Assurance

Replimap includes a dedicated XODR validation module that supports:

  • Structural validation against ASAM OpenDRIVE rules
  • Custom and extended validation rules
  • Full-map and partial-map validation
  • Detailed validation reports with severity levels
  • Location-aware error reporting

Validation can be used interactively during editing or as part of automated quality assurance pipelines.


2.8 XODR Exploration and Analysis

The XODR Explorer module allows deep inspection and analysis of OpenDRIVE maps, providing:

  • Access to full road, lane, and junction graphs
  • Queries over connectivity and relationships
  • Attribute-based and geometry-based filtering
  • Graph traversal and reachability analysis
  • Controlled modification of inspected map elements

This module is particularly useful for debugging, auditing, and advanced analysis tasks.


2.9 Headless and Automated Workflows

All Replimap capabilities are available without any dependency on a user interface. The SDK is suitable for:

  • Command-line tools
  • Batch processing pipelines
  • CI/CD validation workflows
  • Automated map generation and conversion

Long-running operations are exposed through asynchronous APIs to ensure non-blocking integration.


Summary

Together, these capabilities position Replimap as a full-featured OpenDRIVE backend engine, capable of supporting a wide range of authoring, conversion, validation, and analysis use cases. The following sections of this document describe how these capabilities are exposed through the SDK and API, and how they can be used effectively in client applications.

3. Architecture and Usage Model

This section describes how the Replimap SDK and API are designed to be used within client applications. It focuses on practical usage expectations rather than internal implementation details.


3.1 In-Process SDK Model

Replimap is delivered as a native, in-process SDK. The SDK is linked directly into the host application and executes within the same process space. This design enables:

  • High-performance access to complex map data structures
  • Efficient manipulation of large road and lane graphs
  • Low-latency interactive editing workflows
  • Simple integration into desktop and backend applications

The SDK exposes a well-defined public API that serves as the only supported interaction point with the underlying engine. All access to map data and processing functionality must occur through this API.


3.2 Session-Based Usage

All operations in the Replimap SDK are performed within the context of an explicit session.

A session represents: - A single working context - One or more loaded or created maps - The lifetime boundary for allocated resources

Typical usage follows this pattern: 1. Create a session 2. Load or create a map 3. Perform editing, querying, validation, or conversion operations 4. Save or export results 5. Close the session

Sessions provide isolation, predictable resource management, and clear ownership of map state.


3.3 Deterministic and Controlled Execution

The SDK is designed to be deterministic. Given the same inputs and execution order, the API produces the same outputs and results.

Key characteristics include: - No hidden background modifications - No implicit state changes - Explicit control over all mutating operations - Predictable serialization and validation results

This behavior is critical for reproducible workflows, automated pipelines, and long-running integrations.


3.4 Command and Query Separation

The Replimap API follows a clear separation between commands and queries:

  • Commands modify map state
    Examples include creating roads, editing geometry, adding lanes, or modifying connectivity.

  • Queries retrieve information without modifying state
    Examples include geometry sampling, connectivity inspection, attribute access, and spatial queries.

This separation improves: - API clarity - Predictability of side effects - Reasoning about performance - Safe integration into complex applications

Commands and queries are grouped consistently across SDK modules.


3.5 Error Handling Model

The SDK uses an explicit, structured error handling model.

Key principles: - Public API methods do not expose raw exceptions - All recoverable failures are reported through structured result objects - Errors include clear codes, messages, and context - Callers are expected to handle errors explicitly

This approach improves stability in long-running applications and avoids unexpected termination due to unhandled failures.


3.6 Threading and Concurrency Expectations

Unless explicitly stated otherwise: - SDK API calls are expected to be invoked from a controlled execution context - Concurrent access to the same session or map must be managed by the caller - Queries are designed to be side-effect free - Commands must not be executed concurrently on the same mutable map state

Long-running or blocking operations are exposed through asynchronous APIs, described later in this document.


3.7 Asynchronous Operations Overview

Certain operations, such as validation and data conversion, may require significant processing time or external I/O. These operations are exposed as asynchronous jobs.

Asynchronous APIs are designed to: - Avoid blocking the calling thread - Provide progress reporting - Support cancellation - Return structured results upon completion

The detailed usage of asynchronous APIs is covered in a dedicated section later in this document.


Summary

The Replimap SDK and API are designed around a clear, predictable usage model: an in-process, session-based engine with deterministic behavior, explicit error handling, and a strong separation between state-modifying commands and read-only queries. This model enables reliable integration into both interactive tools and automated processing pipelines.

4. Installation and Integration

This section describes how to install and integrate the Replimap SDK and API into a .NET-based application. The SDK is implemented in C# and is designed to be consumed directly by .NET projects as a native, in-process library.


4.1 Supported Platforms

The Replimap SDK supports the following environments:

  • .NET 6.0 or later (recommended)
  • .NET Framework (version as specified per release)
  • Windows desktop applications
  • Backend and headless .NET services
  • Unity-based applications (when targeting a compatible .NET runtime)

Platform-specific requirements, if any, are documented in the release notes for each SDK version.


4.2 SDK Package Contents

The SDK is distributed as a set of managed assemblies and related resources, typically including:

  • Core SDK assemblies (Replimap.*.dll)
  • Optional module assemblies (e.g., HERE2ODR, Validator, Explorer)
  • Supporting configuration files
  • License and version metadata

Each assembly exposes a clearly defined public API and is versioned consistently across the SDK.


4.3 Installation Methods

This approach is suitable for desktop applications, internal tools, and environments with strict dependency control.

Steps: 1. Copy the provided SDK .dll files into a directory within your project or solution. 2. In your .NET project, add references to the required assemblies. 3. Ensure all dependent assemblies are available at runtime.

This method provides full control over SDK versions and is well-suited for long-term integrations.


Option 2: NuGet Package (If Provided)

If the SDK is distributed via a NuGet package:

  1. Add the package source (if private).
  2. Install the required Replimap packages via NuGet.
  3. Restore dependencies as part of your build process.

NuGet-based distribution simplifies updates and dependency management but may be optional depending on deployment requirements.


4.4 Referencing the SDK in a .NET Project

After adding the SDK assemblies to your project, reference the primary namespaces exposed by the SDK.

Typical usage begins by importing the core namespaces:

using Replimap.Core;
using Replimap.Geometry;
using Replimap.Roads;
using Replimap.Validation;
using Replimap.Here2Odr;
using Replimap.Explorer;

Note: Only the modules required for a given application need to be referenced.


4.5 Initializing the SDK

Integration typically begins by creating a session that represents the working context for all subsequent operations.
A minimal initialization flow is as follows:

var session = ReplimapSession.Create();

var map = session.CreateMap();
// or
var map = session.LoadMap("example.xodr");

The session manages the lifetime of maps and internal resources. Applications are expected to explicitly close or dispose of sessions when they are no longer needed.


4.6 API Access Model

The Replimap SDK exposes all functionality through session-scoped module APIs.

APIs are not static, nor are they created independently. Instead, a session acts as the single access point to all SDK modules.

A session:

  • Owns all API instances
  • Defines their lifetime
  • Ensures deterministic and isolated execution

All API surfaces are exposed as properties of the session and are valid only while the session is active.

API Acquisition Pattern

The following pattern is used consistently across the SDK and is assumed by all examples in this document:

var session = ReplimapSession.Create();

// Core editing APIs
var roadApi       = session.Roads;
var geometryApi   = session.Geometry;
var junctionApi   = session.Junctions;

// Objects and traffic elements
var objectApi     = session.Objects;
var signalApi     = session.Signals;
var controllerApi = session.Controllers;

// Utilities and analysis
var utilitiesApi  = session.Utilities;
var validatorApi  = session.Validator;
var explorerApi   = session.Explorer;

// Conversion
var here2odrApi   = session.Here2Odr;

Notes

  • All APIs are session-scoped.
  • APIs must not be used after the session is disposed.
  • Handles returned by APIs are valid only within the owning session.

This model avoids global state, enables deterministic behavior, and supports both interactive and headless workflows.

Active Map Selection

For convenience, SDK APIs that do not take a MapHandle operate on the session’s active map.

For multi-map workflows, most map-mutating commands also provide overloads that accept a MapHandle (for example, CreateRoad(MapHandle, ...)). These overloads let you target a specific map without changing the session’s active map.

Important Usage Guidance

When developing applications that use multiple maps, involve modular architectures, perform background processing, or use long-lived sessions, it is strongly recommended to use API variants that explicitly accept a MapHandle.

Relying on the session’s active map is intended primarily for simple scripts, code examples, or interactive tools. In production systems or complex/multi-map workflows, avoid depending on the active map to ensure clear and predictable map targeting.

Active map rules: - CreateMap() and LoadMap(...) set the newly created/loaded map as active. - You can switch the active map explicitly using SetActiveMap(...). - Use GetActiveMap() to inspect the current active map.

Example: switching the active map

var session = ReplimapSession.Create();

var mapA = session.CreateMap().Value;
var mapB = session.LoadMap("city.xodr").Value;

// LoadMap makes mapB active; switch back to mapA
session.SetActiveMap(mapA);

var road = session.Roads.CreateRoad("R_Main", RoadRule.RightHandTraffic).Value;

❌ Anti-pattern: Relying on the session’s active map across multiple classes or modules, as changes to the active map are global to the session and can lead to unintended edits.


4.7 Quick Start | Hello World Example

This section provides a minimal, complete example that demonstrates how to:

  • Create a session
  • Create a map
  • Create a road
  • Add basic geometry
  • Save the map to an OpenDRIVE file

This example assumes the SDK is already installed (see Section 4.3).

Step 1: Create a New Console Application

Create a new C# console application and add the required SDK references.

Step 2: Complete Example

// Program.cs

using System;
using Replimap.Core;
using Replimap.Roads;
using Replimap.Geometry;

namespace ReplimapHelloWorld
{
    class Program
    {
        static void Main(string[] args)
        {
            // Create a session
            using var session = ReplimapSession.Create();

            // Access required APIs
            var roadApi     = session.Roads;
            var geometryApi = session.Geometry;

            // Create a new map
            var mapResult = session.CreateMap();
            if (!mapResult.IsSuccess)
            {
                Console.WriteLine($"Failed to create map: {mapResult.Error}");
                return;
            }

            var map = mapResult.Value;

            // Create a road
            var roadResult = roadApi.CreateRoad(
                map,
                "R1",
                RoadRule.RightHandTraffic
            );
            // Note: Passing MapHandle explicitly is the recommended pattern

            if (!roadResult.IsSuccess)
            {
                Console.WriteLine($"Failed to create road: {roadResult.Error}");
                return;
            }

            var road = roadResult.Value;

            // Add a simple line geometry to the road
            var geometryResult = geometryApi.AddLineGeometry(
                road,
                length: 100.0
            );

            if (!geometryResult.IsSuccess)
            {
                Console.WriteLine($"Failed to add geometry: {geometryResult.Error}");
                return;
            }

            // Save the map
            var saveResult = session.SaveMap(map, "hello_world.xodr");
            if (!saveResult.IsSuccess)
            {
                Console.WriteLine($"Failed to save map: {saveResult.Error}");
                return;
            }

            Console.WriteLine("Hello World map created successfully!");
        }
    }
}

Expected Result

A file named hello_world.xodr is created in the application directory.

The map contains:

  • One road
  • A single straight geometry segment

No errors are produced if the SDK is correctly installed and configured.

Notes

  • All APIs are accessed via the session (see Section 4.6).
  • Error handling uses the Result<T> pattern consistently across the SDK.
  • This example represents the smallest valid OpenDRIVE map that can be authored using Replimap.

4.8 Error Handling Example

All Replimap SDK APIs return structured Result or Result<T> objects.

Applications are expected to explicitly inspect results and handle failures in a controlled manner.

The following example demonstrates how to access detailed error information when an operation fails.

Example: Handling and Inspecting Errors

var roadResult = roadApi.CreateRoad(map, "R1", RoadRule.RightHandTraffic);

if (!roadResult.IsSuccess)
{
    var error = roadResult.Error;

    Console.WriteLine("Operation failed");
    Console.WriteLine($"Error Code : {error.ErrorCode}");
    Console.WriteLine($"Category   : {error.Category}");
    Console.WriteLine($"Severity   : {error.Severity}");
    Console.WriteLine($"Message    : {error.Message}");

    // Optional contextual information
    if (error.Context != null)
        Console.WriteLine($"Context    : {error.Context}");

    return;
}

Handling Specific Error Codes

Applications may handle specific error conditions explicitly by inspecting the error code.

if (!roadResult.IsSuccess)
{
    switch (roadResult.Error.ErrorCode)
    {
        case ErrorCode.DuplicateRoadId:
            Console.WriteLine("A road with this ID already exists.");
            break;

        case ErrorCode.InvalidRoadRule:
            Console.WriteLine("The specified road rule is not valid.");
            break;

        default:
            Console.WriteLine($"Unhandled error: {roadResult.Error.Message}");
            break;
    }
}

Notes - Public APIs do not throw raw exceptions under normal operation. - All recoverable failures are reported via structured error objects. - Error codes are stable and documented in Section 17.12 – Common Error Codes Reference. - This pattern applies uniformly to synchronous and asynchronous APIs.


4.9 Managing External Credentials

Certain modules, such as HERE2ODR, require external credentials (e.g., HERE API keys).

Credential handling is designed to be explicit and controlled by the integrating application. Typical patterns include:

  • Passing credentials via configuration objects
  • Loading credentials from environment variables
  • Using secure storage mechanisms provided by the host system

Important: Credentials are never embedded directly into the SDK and are not persisted unless explicitly configured by the application.


4.10 Build and Deployment Considerations

When deploying an application that uses the Replimap SDK:

  • Ensure all required SDK assemblies are included in the output directory
  • Verify that the target .NET runtime version matches the SDK requirements
  • Include any native or data dependencies referenced by optional modules
  • Validate licensing and credential availability in the target environment

For headless or batch applications, no additional UI or rendering dependencies are required.


4.11 Version Compatibility

Each SDK release is versioned and designed to be consumed as a coherent set of assemblies. Mixing assemblies from different SDK versions is not supported.

Compatibility guarantees, deprecation policies, and upgrade guidance are described in the Versioning, Compatibility, and Support section of this document.

5. SDK Overview and Module Organization

The Replimap SDK is organized into a set of clearly defined modules, each responsible for a specific aspect of OpenDRIVE map authoring, processing, conversion, or analysis. This modular structure allows applications to integrate only the functionality they require, while maintaining a consistent and predictable API surface across the SDK.

At a high level, the SDK is composed of a core layer that manages sessions and maps, along with a collection of functional modules that operate on map data through well-defined APIs.


5.1 Core Module

The Core module provides the foundational building blocks required to work with the SDK. All other modules depend on this layer.

Responsibilities include: - Session creation and lifecycle management - Map creation, loading, and saving - Map metadata access and modification - Global configuration and execution context - Common result and error types used across the SDK

The Core module is always required and serves as the primary entry point into the SDK.


5.2 Geometry and Spatial Module

The Geometry module provides APIs for defining, modifying, and querying geometric data associated with roads and lanes.

Key responsibilities: - Road plan-view geometry (lines, arcs, spirals, parametric curves) - Elevation profiles - Superelevation and lateral shapes - Coordinate system conversions - Sampling and projection utilities - Spatial and distance-based queries

This module underpins most authoring and analysis workflows and is used extensively by higher-level modules.


5.3 Roads and Lanes Module

The Roads and Lanes module exposes APIs for creating and managing the structural elements of an OpenDRIVE map.

Responsibilities include: - Road creation, deletion, and modification - Lane section management - Lane creation, removal, and reindexing - Lane widths, borders, offsets, and heights - Road and lane connectivity - Topology consistency utilities

This module represents the core OpenDRIVE data model and is central to most SDK usage scenarios.


5.4 Junctions Module

The Junctions module focuses on modeling complex connectivity between roads.

Responsibilities include: - Junction creation and deletion - Road-to-junction associations - Lane-to-lane connections within junctions - Contact point management - Junction consistency and integrity checks - Automatic junction generation and repair utilities

This module is typically used in conjunction with the Roads and Lanes module when building connected road networks.


5.5 Objects, Signals, and Controllers Module

This module provides APIs for managing roadside and traffic-related elements defined in OpenDRIVE.

Responsibilities include: - Roadside objects (e.g., guardrails, barriers, poles, trees, buildings) - Parametric and repeated objects - Traffic signals and signal dependencies - Signal controllers and phase definitions - Object and signal placement relative to roads and lanes

These APIs allow detailed modeling of the environment and traffic infrastructure associated with a road network.


5.6 Validation Module (XODR Validator)

The Validation module exposes APIs for validating OpenDRIVE maps against structural and semantic rules.

Responsibilities include: - Validation against ASAM OpenDRIVE specifications - Execution of custom validation rules - Full-map and partial-map validation - Generation of structured validation reports - Severity classification and error localization

Validation can be invoked interactively during authoring or as part of automated quality assurance workflows.


5.7 HERE2ODR Conversion Module

The HERE2ODR module provides APIs for converting HERE map data into OpenDRIVE format.

Responsibilities include: - Downloading HERE tiles using bounding boxes or GeoJSON polygons - Tile-based conversion using explicit tile identifiers - Processing encoded HERE HD map data - Route-based conversion using HERE Routing APIs - Path-matching conversion for selective road extraction - Conversion configuration and credential handling

This module is typically used for map generation and data ingestion workflows.


5.8 XODR Explorer Module

The XODR Explorer module provides advanced inspection and analysis capabilities for OpenDRIVE maps.

Responsibilities include: - Loading and parsing OpenDRIVE data - Exploring road, lane, and junction graphs - Connectivity and relationship queries - Attribute-based and geometry-based filtering - Controlled modification of inspected map elements

This module is particularly useful for debugging, auditing, and analytical applications.


5.9 Utilities and Shared Components

In addition to the primary modules, the SDK includes shared utility components that support common tasks, such as:

  • Progress reporting
  • Asynchronous job management
  • Diagnostics and logging
  • Batch operation helpers

These components are used internally by multiple modules and may also be exposed where appropriate.


Summary

The modular organization of the Replimap SDK allows developers to reason about functionality at a high level while providing fine-grained control over specific aspects of OpenDRIVE map processing. Subsequent sections of this document describe each module’s API in detail, along with usage patterns and examples.

6. Core SDK Concepts

This section introduces the key concepts required to use the Replimap SDK and API correctly and efficiently. These concepts apply consistently across all modules.


6.1 Sessions

A session represents the primary execution context for all SDK operations. Every interaction with the Replimap SDK occurs within a session.

Key characteristics: - A session owns all loaded and created maps - A session defines the lifetime of allocated resources - Sessions provide isolation between independent workflows

Note: A session may own multiple maps simultaneously.
Applications are encouraged to pass MapHandle explicitly to APIs when working with more than one map.

Typical usage: 1. Create a session 2. Perform operations on one or more maps 3. Close or dispose the session when finished

Applications should explicitly manage session lifetimes to ensure predictable resource usage.


6.2 Maps

A map represents an in-memory OpenDRIVE data model. Maps can be created from scratch or loaded from existing XODR files.

Maps are: - Fully mutable through command APIs - Queryable through read-only APIs - Owned by a session - Explicitly saved or exported by the caller

The SDK does not perform implicit saving or background modification of map data.


6.3 Handles and Object References

The SDK uses handles or lightweight references to identify and operate on map elements such as roads, lanes, junctions, objects, and signals.

Key principles: - Handles uniquely identify elements within a map - Handles remain valid as long as the referenced element exists - Direct access to internal data structures is not exposed

This approach ensures API stability and prevents accidental corruption of internal state.


6.4 Command-Based Operations

Commands are API methods that modify map state.

Examples include: - Creating or deleting roads - Editing geometry or lane attributes - Modifying connectivity - Adding or removing objects or signals

Commands are: - Explicit - Deterministic - Executed in the order invoked - Expected to be error-checked by the caller

Applications should group related commands when performing complex edits to improve clarity and performance.


6.5 Query-Based Operations

Queries are API methods that retrieve information without modifying map state.

Examples include: - Geometry sampling - Connectivity inspection - Attribute queries - Spatial and graph-based searches

Queries are: - Side-effect free - Safe to call repeatedly - Suitable for inspection, analysis, and visualization logic


6.6 Result-Based API Pattern

All public API methods return structured result objects rather than throwing raw exceptions.

A result typically contains: - A success or failure indicator - A return value (for successful operations) - An error object (for failed operations)

This pattern ensures: - Predictable error handling - Safe integration into long-running applications - Clear separation between control flow and error reporting

Callers are expected to check results explicitly and handle failures appropriately.


6.7 Error Categories and Recoverability

Errors reported by the SDK are categorized to help applications determine appropriate responses.

Common categories include: - Invalid input or configuration - Structural or consistency violations - Unsupported operations - External dependency failures - Internal execution errors

Most errors are recoverable, allowing applications to continue operating after handling the failure. Fatal conditions are explicitly documented where applicable.


6.8 Deterministic Behavior Guarantees

The SDK is designed to be deterministic.

This means: - Identical inputs produce identical outputs - Operations do not rely on hidden state or randomness - Serialization and validation results are repeatable

Determinism is essential for testing, automation, and large-scale production workflows.


Summary

Understanding these core concepts—sessions, maps, handles, command and query separation, and result-based error handling—is essential for effective use of the Replimap SDK and API. The following sections build on these concepts to describe the individual modules and their APIs in detail.

7. Core SDK APIs

This section introduces the core APIs that form the entry point to the Replimap SDK. These APIs are required for initializing the SDK, managing sessions, loading and saving maps, and accessing global map-level information. All other modules build upon these core APIs.


7.1 Session APIs

Sessions represent the primary execution context for all SDK operations. A session must be created before any map or processing API can be used.

CreateSession

Creates a new SDK session.

Description
Initializes a new execution context and allocates internal resources required by the SDK.

Typical Usage

var session = ReplimapSession.Create();

Notes

  • A session is required for all subsequent operations.
  • Multiple sessions may exist simultaneously, but must be managed explicitly by the application.

CloseSession / Dispose

Releases all resources associated with a session.

Description
Terminates the session and invalidates all maps and handles owned by it.

Typical Usage

session.Dispose();

Notes - Applications should always close sessions explicitly. - Using a disposed session results in an error response.


7.2 Map Creation and Loading APIs

Maps represent in-memory OpenDRIVE data models that can be created from scratch or loaded from existing files.

CreateMap

Creates a new empty map within the session.

Signature

Result<MapHandle> CreateMap();

Example

var result = session.CreateMap();
if (!result.IsSuccess)
{
    HandleError(result.Error);
}
var map = result.Value;

LoadMap

Loads an OpenDRIVE map from a file.

Signature

Result<MapHandle> LoadMap(string filePath);

Example

var mapResult = session.LoadMap("example.xodr");
if (!mapResult.IsSuccess)
{
    HandleError(mapResult.Error);
}
var map = mapResult.Value;

Notes - The SDK does not modify the source file during loading. - Structural validation is not automatically performed unless explicitly requested.

LoadMapFromString / LoadMapFromStream

Loads an OpenDRIVE map from a string or stream.

Use Cases - Integration with network-based data sources - In-memory processing pipelines - Testing and automation workflows


7.3 Map Saving and Export APIs

Saving and exporting maps is an explicit operation controlled by the application.

SaveMap

Saves a map to an OpenDRIVE file.

Signature

Result SaveMap(MapHandle map, string filePath);

Example

var saveResult = session.SaveMap(map, "output.xodr");
if (!saveResult.IsSuccess)
{
    HandleError(saveResult.Error);
}

ExportMap

Exports a map to an OpenDRIVE file with configurable export options, enabling the map to be transformed to suit a particular OpenDRIVE version, downstream toolchain, or consumer.

Export operations may adapt and filter map content to satisfy target constraints while ensuring structural correctness is preserved.

ExportMap is typically used for: - Simulator and toolchain integration - Batch processing, automation pipelines - Producing reduced or specialized map variants

Signature

Result ExportMap(
    MapHandle map,
    string filePath,
    ExportOptions options
);

ExportOptions control export behavior, such as: - Target OpenDRIVE version (e.g., 1.6) - Toolchain/consumer profile - Feature inclusion/exclusion (objects, signals, controllers, etc.) - Formatting and serialization preferences

Public Types

struct ExportOptions
{
    // Target OpenDRIVE version for export
    OpenDriveVersion TargetOpenDriveVersion;

    // Optional toolchain / consumer hint
    ExportToolchain TargetToolchain;

    // Feature inclusion flags
    bool IncludeRoads;        // default: true
    bool IncludeLanes;        // default: true
    bool IncludeJunctions;    // default: true
    bool IncludeObjects;      // default: true
    bool IncludeSignals;      // default: true
    bool IncludeControllers;  // default: true

    // Serialization / formatting options
    ExportFormatting Formatting;

    // Predefined default configuration
    static ExportOptions Default;
}

enum OpenDriveVersion
{
    V1_6
    // Future versions added here
}

enum ExportToolchain
{
    Generic,
    Simulator,
    Validator,
    Custom
}

struct ExportFormatting
{
    bool DeterministicOutput;
    int NumericPrecision;
}

Usage Examples

Example 1: Export using default options

var exportResult = session.ExportMap(
    map,
    "export_default.xodr",
    ExportOptions.Default
);

if (!exportResult.IsSuccess)
{
    HandleError(exportResult.Error);
}

Example 2: Export targeting OpenDRIVE 1.6

var options = new ExportOptions
{
    TargetOpenDriveVersion = OpenDriveVersion.V1_6
};

session.ExportMap(
    map,
    "export_odr16.xodr",
    options
);

Example 3: Export without objects and signals

var options = new ExportOptions
{
    TargetOpenDriveVersion = OpenDriveVersion.V1_6,
    IncludeObjects = false,
    IncludeSignals = false,
    IncludeControllers = false
};

session.ExportMap(
    map,
    "export_geometry_only.xodr",
    options
);

Notes - Export does not modify the in-memory map. - Unsupported options for a target version or toolchain result in an explicit error. - Additional OpenDRIVE versions and export filters may be added in future SDK releases.


7.4 Map Metadata APIs

Metadata APIs provide access to high-level information about a map.

GetMapMetadata

Retrieves metadata associated with a map.

Examples of Metadata - OpenDRIVE version - Geo-reference information - Map bounds - User-defined attributes

Example

var metadataResult = session.GetMapMetadata(map);
if (metadataResult.IsSuccess)
{
    var metadata = metadataResult.Value;
}

UpdateMapMetadata

Updates map-level metadata fields.

Notes - Metadata updates do not modify geometric or topological content. - Changes are reflected in exported OpenDRIVE files.


7.5 Map Lifecycle Utilities

These APIs assist with managing map state during editing workflows.

CloneMap

Creates a deep copy of a map.

Use Cases - Branching workflows - Undo/redo systems - Scenario experimentation

ClearMap

Removes all content from a map while preserving the map instance.

SetActiveMap

Sets the active map for the session. All map-modifying APIs that do not take a MapHandle operate on this map.

Signature

Result SetActiveMap(MapHandle map);

Example

var mapA = session.CreateMap().Value;
var mapB = session.LoadMap("city.xodr").Value;

// Switch active map to mapA before editing
session.SetActiveMap(mapA);

GetActiveMap

Returns the current active map for the session.

Signature

Result<MapHandle> GetActiveMap();

Example

var activeMap = session.GetActiveMap().Value;


7.6 Error Handling in Core APIs

All core APIs return structured result objects.

General Pattern

var result = SomeApiCall();
if (!result.IsSuccess)
{
    Log(result.Error);
    return;
}

Common Error Scenarios - Invalid input parameters - File I/O failures - Unsupported OpenDRIVE versions - Session or map lifecycle violations

Errors are reported explicitly and do not cause application termination.


Summary

The Core SDK APIs provide the foundation for all interactions with the Replimap SDK. By creating and managing sessions, loading and saving maps, and accessing map-level metadata, applications establish the context in which all authoring, validation, conversion, and analysis workflows operate.

Subsequent sections describe the APIs exposed by individual functional modules in greater detail.

8. Geometry and Spatial APIs

The Geometry and Spatial APIs provide low-level control over the geometric foundations of an OpenDRIVE map. These APIs are used to define, modify, and query road reference lines, elevation profiles, superelevation, lateral shapes, and spatial relationships.

All geometry APIs operate on existing map elements and follow the command/query separation model described earlier.


8.1 Overview

This module is responsible for:

  • Road plan-view geometry
  • Elevation and vertical alignment
  • Superelevation and lateral deformation
  • Coordinate transformations
  • Geometry sampling and spatial queries

These APIs are foundational and are heavily used by higher-level modules such as Roads, Lanes, Junctions, Objects, and Validation.


8.2 Public Types

enum GeometryType
{
    Line,
    Arc,
    Spiral,
    Poly3,
    ParamPoly3
}

struct GeometryHandle { }
struct ElevationHandle { }
struct SuperelevationHandle { }
struct LateralShapeHandle { }

struct SRange
{
    double SStart;
    double SEnd;
}


struct Vector2
{
    double X; // X-coordinate in map space
    double Y; // Y-coordinate in map space
}

struct XYCoordinate
{
    double X; // X-coordinate in map space
    double Y; // Y-coordinate in map space
}

struct PointAndHeading
{
    Vector2 Point;   // Position on the road reference line
    double Heading;  // Tangent direction at this point (radians)
}

struct RoadProjection
{
    double S;               // Longitudinal position along the road reference line
    double T;               // Lateral offset from the reference line
    Vector2 ProjectedPoint; // Closest point on the road reference line
    double Distance;        // Euclidean distance from the original point
}

struct LaneProjection
{
    double S;               // Longitudinal position along the lane
    double T;               // Lateral offset relative to the lane center or border
    Vector2 ProjectedPoint; // Closest point within the lane
    double Distance;        // Euclidean distance from the original point
    bool IsInsideLane;      // True if the projected point lies within lane boundaries
}

struct BoundingBox
{
    Vector2 Min; // Lower-left corner of the bounding box
    Vector2 Max; // Upper-right corner of the bounding box
}

8.3 PlanView Geometry APIs

Commands

AddGeometrySegment
Adds a geometry segment to a road’s plan view.

Signature

Result<GeometryHandle> AddGeometrySegment(
    RoadHandle road,
    GeometryType type,
    GeometryParameters parameters
);
Errors - InvalidRoadHandle - InvalidGeometryParameters - GeometryContinuityViolation

Example

var result = geometryApi.AddGeometrySegment(
    road,
    GeometryType.Line,
    new LineGeometryParameters { Length = 50.0 }
);

if (!result.IsSuccess)
{
    Log(result.Error);
}

InsertGeometrySegment
Inserts a geometry segment at a specific s position.

Result<GeometryHandle> InsertGeometrySegment(
    RoadHandle road,
    double sPosition,
    GeometryType type,
    GeometryParameters parameters
);

UpdateGeometrySegment
Updates parameters of an existing geometry segment.

Result UpdateGeometrySegment(
    GeometryHandle geometry,
    GeometryParameters newParameters
);

RemoveGeometrySegment
Removes a geometry segment.

Result RemoveGeometrySegment(GeometryHandle geometry);

TrimGeometry
Trims road geometry to a specified range.

Result TrimGeometry(
    RoadHandle road,
    SRange range
);

SplitRoadGeometry

Splits a road into two roads at a specified longitudinal position.

Result<(RoadHandle FirstRoad, RoadHandle SecondRoad)> SplitRoadGeometry(
    RoadHandle road,
    double sSplit
);
Queries

GetGeometrySegments

Result<IReadOnlyList<GeometryHandle>> GetGeometrySegments(
    RoadHandle road
);

GetGeometryAtS
Returns the geometry segment active at s.

Result<GeometryHandle> GetGeometryAtS(
    RoadHandle road,
    double s
);

GetRoadLength

Result<double> GetRoadLength(RoadHandle road);

SamplePlanView
Samples plan-view geometry at s.

Result<PlanViewSample> SamplePlanView(
    RoadHandle road,
    double s
);

GetPoint

Returns the Cartesian position on the road reference line at a given s.

Result<Vector2> GetPoint(
    RoadHandle road,
    double s
);
  • s is measured along the road reference line
  • The returned point is in the map’s Cartesian coordinate system

GetHeading

Returns the heading (orientation) of the road reference line at a given s.

Result<double> GetHeading(
    RoadHandle road,
    double s
);
  • Heading is returned in radians
  • Measured relative to the map’s coordinate frame

GetPointAndHeading

Returns both position and heading at a given s.

Result<PointAndHeading> GetPointAndHeading(
    RoadHandle road,
    double s
);
  • This is a convenience API equivalent to calling GetPoint and GetHeading at the same s.

GetPointsOnLength

Samples multiple points along the road reference line over a given length.

Result<IReadOnlyList<Vector2>> GetPointsOnLength(
    RoadHandle road,
    double sStart,
    double length,
    double step
);
  • Sampling begins at sStart
  • Points are generated at intervals of step

Useful for: - Visualization - Trajectory generation - Collision checks - Geometry inspection


8.4 Elevation Profile APIs

Commands

AddElevationSegment

Result<ElevationHandle> AddElevationSegment(
    RoadHandle road,
    double sStart,
    ElevationPolynomial polynomial
);

UpdateElevationSegment

Result UpdateElevationSegment(
    ElevationHandle elevation,
    ElevationPolynomial polynomial
);

RemoveElevationSegment

Result RemoveElevationSegment(ElevationHandle elevation);

Queries

GetElevationAtS

Result<double> GetElevationAtS(
    RoadHandle road,
    double s
);

GetSlopeAtS

Result<double> GetSlopeAtS(
    RoadHandle road,
    double s
);


8.5 Superelevation APIs

Commands

AddSuperelevationSegment

Result<SuperelevationHandle> AddSuperelevationSegment(
    RoadHandle road,
    double sStart,
    SuperelevationPolynomial polynomial
);

RemoveSuperelevationSegment

Result RemoveSuperelevationSegment(
    SuperelevationHandle superelevation
);

Queries

GetSuperelevationAtS

Result<double> GetSuperelevationAtS(
    RoadHandle road,
    double s
);


8.6 Lateral Shape APIs

Commands

AddLateralShape

Result<LateralShapeHandle> AddLateralShape(
    RoadHandle road,
    double sStart,
    LateralShapePolynomial polynomial
);

RemoveShape

Removes a previously defined lateral elevation shape from the road.

Result RemoveShape(
    RoadHandle road,
    double sOffset
);
Queries

EvaluateLateralShape

Result<double> EvaluateLateralShape(
    RoadHandle road,
    double s,
    double t
);


8.7 Coordinate Transformation APIs

Queries

ConvertXYToST

Result<STCoordinate> ConvertXYToST(
    RoadHandle road,
    double x,
    double y
);

ConvertSTToXY

Result<XYCoordinate> ConvertSTToXY(
    RoadHandle road,
    double s,
    double t
);

ConvertToGeographic

Result<GeoCoordinate> ConvertToGeographic(
    double x,
    double y,
    double z
);


8.8 Spatial Queries and Sampling

Queries

FindNearestRoad

Result<RoadHandle> FindNearestRoad(
    double x,
    double y
);

FindNearestLane

Result<LaneHandle> FindNearestLane(
    double x,
    double y
);

GetMapBoundingBox

Result<BoundingBox> GetMapBoundingBox();

DistanceToRoad
Computes the shortest distance from a point to a road reference line.

Result<double> DistanceToRoad(
    RoadHandle road,
    Vector2 point
);
- Distance is measured in the map’s Cartesian coordinate system - Useful for proximity checks and snapping logic

DistanceToLane
Computes the shortest distance from a point to a lane surface.

Result<double> DistanceToLane(
    LaneHandle lane,
    Vector2 point
);
- Takes lane borders and widths into account
- Used for lane assignment and validation

ProjectPointToRoad
Projects a point onto the road reference line.

Result<RoadProjection> ProjectPointToRoad(
    RoadHandle road,
    Vector2 point
);
- Returns: - Closest longitudinal position s - Lateral offset t - Projected Cartesian point

ProjectPointToLane
Projects a point onto a lane surface.

Result<LaneProjection> ProjectPointToLane(
    LaneHandle lane,
    Vector2 point
);
- Returns: - Closest position within the lane - Distance to lane center or border - Useful for snapping and hit-testing

FindRoadIntersections
Finds all geometric intersections between two roads.

Result<IReadOnlyList<Vector2>> FindRoadIntersections(
    RoadHandle roadA,
    RoadHandle roadB
);
- Considers plan view geometry only - Does not imply topological connectivity

RoadsIntersect
Checks whether two roads geometrically intersect.

Result<bool> RoadsIntersect(
    RoadHandle roadA,
    RoadHandle roadB
);
- Lightweight boolean check - Useful for validation and pre-filtering

GetRoadBoundingBox
Returns the axis-aligned bounding box of a road.

Result<BoundingBox> GetRoadBoundingBox(
    RoadHandle road
);
- Computed from actual geometry - Always reflects current road state - Differs from metadata bounding boxes

CalculateAngleBetweenRoads
Computes the angle between two roads at their closest intersection or approach.

Result<double> CalculateAngleBetweenRoads(
    RoadHandle roadA,
    RoadHandle roadB
);
- Angle returned in radians - Useful for junction analysis and validation

Notes

  • All methods are pure and deterministic
  • No geometry or topology is modified
  • Errors are returned if:
  • Handles are invalid
  • Geometry is undefined
  • Roads do not intersect where required

8.9 Geometry Validation Utilities

Commands

ValidateGeometryContinuity

Result ValidateGeometryContinuity(
    RoadHandle road
);

Queries

GetGeometryDiscontinuities

Result<IReadOnlyList<double>> GetGeometryDiscontinuities(
    RoadHandle road
);


8.10 Usage Example

var road = roadApi.CreateRoad(map, "R1").Value;

geometryApi.AddGeometrySegment(
    road,
    GeometryType.Line,
    new LineGeometryParameters { Length = 100.0 }
);

geometryApi.AddElevationSegment(
    road,
    0.0,
    new ElevationPolynomial { A = 0, B = 0, C = 0, D = 0 }
);

var elevation = geometryApi.GetElevationAtS(road, 50.0);

Summary

The Geometry and Spatial APIs provide full control over the geometric definition and evaluation of OpenDRIVE maps. These APIs are fundamental to all authoring, conversion, validation, and analysis workflows supported by the Replimap SDK.

9. Road and Lane APIs

The Road and Lane APIs provide full control over the structural and topological elements of an OpenDRIVE map. These APIs are responsible for creating and modifying roads, lane sections, lanes, lane attributes, and lane-level connectivity.

Roads are created as topological entities. Geometry and spatial properties are defined separately using Geometry APIs. This separation allows geometry to be modified, replaced, or analyzed without altering road identity or connectivity.

Together with the Geometry APIs, this module forms the core of OpenDRIVE authoring and editing workflows.


9.1 Overview

This module enables applications to:

  • Create and manage roads
  • Define lane sections along roads
  • Add, remove, and modify lanes
  • Control lane widths, borders, offsets, and heights
  • Define predecessor and successor relationships
  • Build and inspect lane-level topology

All operations follow deterministic, command-based execution with explicit error handling.


9.2 Public Types

Handle Types

struct RoadHandle { }
struct LaneSectionHandle { }
struct LaneHandle { }

Road Structure and Topology

enum RoadRule
{
    RightHandTraffic,
    LeftHandTraffic
}

enum LaneSide
{
    Left,
    Center,
    Right
}

enum LaneType
{
    Driving,
    Shoulder,
    Sidewalk,
    Border,
    Median,
    Parking,
    Restricted,
    None
}

Lane Border Geometry

struct BorderPolynomial
{
    double a;  // constant term
    double b;  // linear term
    double c;  // quadratic term
    double d;  // cubic term
}

struct LaneBorder
{
    double sOffset;
    BorderPolynomial polynomial;
}
// Semantics: The lateral position of the lane border at a given s is computed as:
// t(s) = a + b·Δs + c·Δs² + d·Δs³
// where Δs = s - sOffset

Lane Markings

enum LaneMarkingType
{
    Solid,
    Broken,
    SolidSolid,
    BrokenBroken,
    SolidBroken,
    BrokenSolid,
    Curb,
    None
}

enum LaneMarkingColor
{
    White,
    Yellow,
    Red,
    Blue,
    Green,
    Other
}

enum LaneMarkingMaterial
{
    Standard,
    Reflective,
    BottsDots,
    Grass,
    Curb
}

enum LaneMarkingSide
{
    Left,
    Right,
    Center
}

// Lane Marking Definition
struct LaneMarking
{
    double SOffset;                  // Start position along lane/road
    LaneMarkingSide Side;            // Left / Right / Center
    LaneMarkingType Type;
    LaneMarkingColor Color;
    LaneMarkingMaterial Material;
    double Width;                    // In meters
}

Road Type Segmentation

enum RoadType
{
    Unknown,
    Urban,
    Rural,
    Motorway,
    Highway,
    Expressway,
    Residential,
    Service,
    Ramp,
    SlipRoad,
    Roundabout,
    Connector
}

// Road Type Segment Definition
struct RoadTypeSegment
{
    double SStart;     // Start position along the road reference line
    RoadType Type;     // Road functional classification
}

Speed Properties

enum SpeedUnit
{
    MetersPerSecond,
    KilometersPerHour,
    MilesPerHour
}

// Speed Value Definition
struct SpeedValue
{
    double Value;        // Numeric speed value
    SpeedUnit Unit;      // Unit of the speed value
}

// Speed Segment Definition
struct SpeedSegment
{
    double SStart;       // Start position along the road or lane
    SpeedValue Speed;    // Speed value with unit
}

Lane Material

enum LaneMaterialType
{
    Unknown,
    Asphalt,
    Concrete,
    Cobblestone,
    Gravel,
    Dirt,
    Grass,
    Sand,
    Snow,
    Ice,
    PavedShoulder,
    UnpavedShoulder
}

// Lane Material Segment Definition
struct LaneMaterialSegment
{
    double SStart;                // Start position along the road or lane
    LaneMaterialType Material;    // Surface material type
}

Tram Usage

enum TramUsageType
{
    None,        // Lane does not support tram traffic
    Shared,      // Tram shares lane with road vehicles
    Exclusive    // Tram-only lane
}

struct TramLaneSegment
{
    double SStart;             // Start position along the lane
    TramUsageType Usage;       // Tram usage mode
}

9.3 Road APIs

Commands

CreateRoad
Creates a new road and adds it to the map.

Result<RoadHandle> CreateRoad(
    string roadId,
    RoadRule rule
);

Result<RoadHandle> CreateRoad(
    MapHandle map,
    string roadId,
    RoadRule rule
);
Errors

  • DuplicateRoadId
  • InvalidRoadRule

Example

// Target a specific map without changing the active map -- Recommended!
var roadInMapB = roadApi.CreateRoad(mapB, "R2", RoadRule.RightHandTraffic).Value;

// or use the currently active map:
var roadResult = roadApi.CreateRoad("R1", RoadRule.RightHandTraffic);
var road = roadResult.Value;

DeleteRoad

Result DeleteRoad(RoadHandle road);

RenameRoad

Result RenameRoad(
    RoadHandle road,
    string newRoadId
);

ReverseRoadDirection
Reverses the reference line direction and updates dependent data.

Result ReverseRoadDirection(RoadHandle road);

SplitRoad
Splits a road at a given s position.

Result<IReadOnlyList<RoadHandle>> SplitRoad(
    RoadHandle road,
    double sSplit
);

MergeRoads
Merges two compatible roads into one.

Result<RoadHandle> MergeRoads(
    RoadHandle first,
    RoadHandle second
);

Queries

GetRoadById

Result<RoadHandle> GetRoadById(string roadId);

GetAllRoads

Result<IReadOnlyList<RoadHandle>> GetAllRoads();

GetRoadRule

Result<RoadRule> GetRoadRule(RoadHandle road);


9.4 Road Type APIs

Road Type APIs provide control over the functional classification of roads.

Road types describe the intended usage and driving context of a road segment and are used by downstream consumers such as simulators, validators, and export pipelines.

Road Types: - Are defined at the road level - May vary along the road using s-based segments - Do not affect geometry or topology - May influence defaults, validation rules, and export behavior

Commands

AddRoadTypeSegment
Adds a road type segment starting at segment.SStart.

Result AddRoadTypeSegment(
    RoadHandle road,
    RoadTypeSegment segment
);
// Adds a road type segment starting at segment.SStart
// Multiple segments may exist on the same road

UpdateRoadTypeSegment
Updates an existing road type segment identified by SStart.

Result UpdateRoadTypeSegment(
    RoadHandle road,
    RoadTypeSegment segment
);
// Updates an existing road type segment identified by SStart

RemoveRoadTypeSegment
Removes the road type segment that starts at sStart.

Result RemoveRoadTypeSegment(
    RoadHandle road,
    double sStart
);
// Removes the road type segment that starts at sStart

ClearRoadTypeSegments
Removes all road type segments from the road.

Result ClearRoadTypeSegments(
    RoadHandle road
);
// Removes all road type segments from the road

Queries

GetRoadTypeSegments
Returns all road type segments defined on the road, ordered by SStart.

Result<IReadOnlyList<RoadTypeSegment>> GetRoadTypeSegments(
    RoadHandle road
);
// Returns all road type segments defined on the road
// Segments are ordered by SStart

GetRoadTypeAtS
Returns the road type active at longitudinal position s.
If no segment exists, RoadType.Unknown is returned.

Result<RoadType> GetRoadTypeAtS(
    RoadHandle road,
    double s
);
// Returns the road type active at longitudinal position s
// If no segment exists, RoadType.Unknown is returned

Error Handling

Road Type APIs return structured errors in the following cases: - Invalid road handle - Invalid s-position (negative or outside road length) - Overlapping or duplicate road type segments - Attempting to update or remove a non-existent segment

All errors are reported using the standard Result / Result<T> pattern and do not modify road geometry or connectivity.


9.5 Lane Section APIs

Commands

AddLaneSection
Adds a lane section starting at s.

Result<LaneSectionHandle> AddLaneSection(
    RoadHandle road,
    double sStart
);

RemoveLaneSection

Result RemoveLaneSection(
    LaneSectionHandle laneSection
);

SplitLaneSection

Result<IReadOnlyList<LaneSectionHandle>> SplitLaneSection(
    LaneSectionHandle laneSection,
    double sSplit
);

Queries

GetLaneSections

Result<IReadOnlyList<LaneSectionHandle>> GetLaneSections(
    RoadHandle road
);

GetLaneSectionAtS

Result<LaneSectionHandle> GetLaneSectionAtS(
    RoadHandle road,
    double s
);


9.6 Lane APIs

Commands

AddLane
Adds a lane to a lane section.

Result<LaneHandle> AddLane(
    LaneSectionHandle laneSection,
    LaneSide side,
    int laneId,
    LaneType type
);

RemoveLane

Result RemoveLane(LaneHandle lane);

Note: Only outer-most lanes may be removed. Attempting to remove a center lane or an inner lane results in an error. [LaneNotRemovable]

ChangeLaneType

Result ChangeLaneType(
    LaneHandle lane,
    LaneType newType
);

ChangeLaneId

Result ChangeLaneId(
    LaneHandle lane,
    int newLaneId
);

ReverseLaneDirection

Result ReverseLaneDirection(LaneHandle lane);

Queries

GetLanes

Result<IReadOnlyList<LaneHandle>> GetLanes(
    LaneSectionHandle laneSection
);

GetLaneType

Result<LaneType> GetLaneType(LaneHandle lane);

ContainsLane

Checks whether a lane with the specified identifier exists in a lane section.

bool ContainsLane(
    LaneSectionHandle laneSection,
    int laneId
);
- Returns true if the lane exists - Does not modify map state


GetLaneCount

Returns the number of lanes in a lane section.

int GetLaneCount(
    LaneSectionHandle laneSection
);
- Includes left, right, and center lanes - Useful for validation and inspection


AddBorder

Adds or updates a lateral border definition for a lane.

Result AddBorder(
    LaneHandle lane,
    LaneBorder border
);
Lane borders define: - Lane width variation - Lane boundary shape along s

This API is typically used to: - Define lane widths - Modify lane boundaries independently of road geometry


RemoveBorder

Removes an existing border definition from a lane.

Result RemoveBorder(
    LaneHandle lane
);
- Clears the lane’s border information - Restores default or inherited lane width behavior


GetBorder

Retrieves the border definition associated with a lane.

Result<LaneBorder> GetBorder(
    LaneHandle lane
);
- Returns the lane’s border geometry if defined - Useful for inspection, editing, and validation


9.7 Lane Width APIs

Commands

AddLaneWidthSegment

Result AddLaneWidthSegment(
    LaneHandle lane,
    double sOffset,
    WidthPolynomial polynomial
);

UpdateLaneWidthSegment

Result UpdateLaneWidthSegment(
    LaneHandle lane,
    int segmentIndex,
    WidthPolynomial polynomial
);

RemoveLaneWidthSegment

Result RemoveLaneWidthSegment(
    LaneHandle lane,
    int segmentIndex
);

Queries

GetLaneWidthAtS

Result<double> GetLaneWidthAtS(
    LaneHandle lane,
    double s
);


9.8 Lane Offset and Height APIs

Commands

AddLaneOffsetSegment

Result AddLaneOffsetSegment(
    RoadHandle road,
    double sStart,
    OffsetPolynomial polynomial
);

AddLaneHeightSegment

Result AddLaneHeightSegment(
    LaneHandle lane,
    double sStart,
    HeightPolynomial polynomial
);

Queries

GetLaneOffsetAtS

Result<double> GetLaneOffsetAtS(
    RoadHandle road,
    double s
);

GetLaneHeightAtS

Result<double> GetLaneHeightAtS(
    LaneHandle lane,
    double s
);


9.9 Lane Connectivity APIs

Commands

SetLanePredecessor

Result SetLanePredecessor(
    LaneHandle lane,
    LaneHandle predecessor
);

SetLaneSuccessor

Result SetLaneSuccessor(
    LaneHandle lane,
    LaneHandle successor
);

RemoveLaneLinks

Result RemoveLaneLinks(LaneHandle lane);

Queries

GetLanePredecessor

Result<LaneHandle> GetLanePredecessor(LaneHandle lane);

GetLaneSuccessor

Result<LaneHandle> GetLaneSuccessor(LaneHandle lane);

GetLaneConnectivityGraph

Result<LaneConnectivityGraph> GetLaneConnectivityGraph();


9.10 Lane Marking APIs

Lane marking APIs provide programmatic control over lane boundary markings and road-wide default markings. Lane markings define the visual and semantic separation between lanes and are essential for simulation, validation, and downstream consumer compatibility.

Lane markings may be defined at two levels:

  • Lane-level markings – Explicit markings applied directly to a specific lane
  • Road-level default markings – Fallback markings applied when a lane does not define its own marking

Lane-level markings always take precedence over road-level defaults.

All lane marking operations are deterministic and do not modify road geometry.


Lane-Level Lane Markings

Lane-level lane markings define markings on the left, right, or center boundaries of a specific lane. These markings are scoped to the owning lane and override any road-level default markings.

Commands

AddLaneMarking
Result AddLaneMarking(
    LaneHandle lane,
    LaneMarking marking
);
// Adds a lane marking definition to the specified lane
// The marking is applied starting at marking.SOffset
// Overrides any road-level default marking for the same side
UpdateLaneMarking
Result UpdateLaneMarking(
    LaneHandle lane,
    LaneMarking updatedMarking
);
// Updates an existing lane marking on the lane
// The marking is identified by side and sOffset
RemoveLaneMarking
Result RemoveLaneMarking(
    LaneHandle lane,
    double sOffset,
    LaneMarkingSide side
);
// Removes the lane marking defined at the given sOffset and side

Queries

GetLaneMarkings
Result<IReadOnlyList<LaneMarking>> GetLaneMarkings(
    LaneHandle lane
);
// Returns all lane markings explicitly defined on the lane
GetLaneMarkingAtS
Result<LaneMarking> GetLaneMarkingAtS(
    LaneHandle lane,
    double s,
    LaneMarkingSide side
);
// Returns the lane marking active at position s for the given side
// Only considers lane-level markings

Road-Level Default Lane Markings

Road-level default lane markings define fallback markings that apply to all lanes of a road when a lane does not explicitly define its own marking.

These markings are typically used to:

  • Define consistent markings across an entire road
  • Reduce duplication when multiple lanes share the same marking behavior
  • Establish defaults that may be selectively overridden per lane

Commands

Result SetRoadDefaultLaneMarking(
    RoadHandle road,
    LaneMarking marking
);
// Sets or replaces a default lane marking for the road
// Applies to all lanes unless overridden at lane level

Result RemoveRoadDefaultLaneMarking(
    RoadHandle road,
    LaneMarkingSide side
);
// Removes the road-level default marking for the specified side

Queries

Result<IReadOnlyList<LaneMarking>> GetRoadDefaultLaneMarkings(
    RoadHandle road
);
// Returns all default lane markings defined for the road

Effective Lane Marking Resolution

To simplify inspection and downstream usage, the SDK provides a resolved query that applies precedence rules automatically.

Lane-level markings take priority over road-level defaults.

Query

Result<LaneMarking> GetEffectiveLaneMarkingAtS(
    LaneHandle lane,
    double s,
    LaneMarkingSide side
);
// Returns the effective lane marking at position s
// Resolution order:
//   1. Lane-level marking
//   2. Road-level default marking

9.11 Speed Limit APIs

Speed Limit APIs provide control over road-level and lane-level speed limits. Speed limits define the maximum allowed speed for vehicles and are used by simulators, routing systems, validation workflows, and export pipelines.

Speed limits: - May be defined at both road and lane level - May vary along the road or lane using s-based segments - Are semantic attributes and do not affect geometry or topology - Support multiple units without implicit conversion - Lane-level speed limits always take precedence over road-level speed limits.

Road-Level Speed Limits

Road-level speed limits define default speed limits for all lanes of a road unless explicitly overridden by lane-level definitions.

Commands

AddRoadSpeedSegment

Result AddRoadSpeedSegment(
    RoadHandle road,
    SpeedSegment segment
);
// Adds a road-level speed limit starting at segment.SStart

UpdateRoadSpeedSegment

Result UpdateRoadSpeedSegment(
    RoadHandle road,
    SpeedSegment segment
);
// Updates an existing road-level speed segment identified by SStart

RemoveRoadSpeedSegment

Result RemoveRoadSpeedSegment(
    RoadHandle road,
    double sStart
);
// Removes the road-level speed segment that starts at sStart

ClearRoadSpeedSegments

Result ClearRoadSpeedSegments(
    RoadHandle road
);
// Removes all road-level speed segments from the road

Queries

GetRoadSpeedSegments

Result<IReadOnlyList<SpeedSegment>> GetRoadSpeedSegments(
    RoadHandle road
);
// Returns all road-level speed segments ordered by SStart

GetRoadSpeedAtS

Result<SpeedValue> GetRoadSpeedAtS(
    RoadHandle road,
    double s
);
// Returns the road-level speed limit active at position s

Lane-Level Speed Limits

Lane-level speed limits define speed restrictions specific to a lane and override any road-level speed limits.

Commands

AddLaneSpeedSegment

Result AddLaneSpeedSegment(
    LaneHandle lane,
    SpeedSegment segment
);
// Adds a lane-level speed limit starting at segment.SStart

UpdateLaneSpeedSegment

Result UpdateLaneSpeedSegment(
    LaneHandle lane,
    SpeedSegment segment
);
// Updates an existing lane-level speed segment identified by SStart

RemoveLaneSpeedSegment

Result RemoveLaneSpeedSegment(
    LaneHandle lane,
    double sStart
);
// Removes the lane-level speed segment that starts at sStart

ClearLaneSpeedSegments

Result ClearLaneSpeedSegments(
    LaneHandle lane
);
// Removes all lane-level speed segments from the lane

Queries

GetLaneSpeedSegments

Result<IReadOnlyList<SpeedSegment>> GetLaneSpeedSegments(
    LaneHandle lane
);
// Returns all lane-level speed segments ordered by SStart

GetLaneSpeedAtS

Result<SpeedValue> GetLaneSpeedAtS(
    LaneHandle lane,
    double s
);
// Returns the lane-level speed limit active at position s

Effective Speed Resolution

For convenience and downstream usage, the SDK provides a resolved query that applies precedence rules automatically.

Lane-level speed limits override road-level speed limits.

Query

GetEffectiveSpeedAtS

Result<SpeedValue> GetEffectiveSpeedAtS(
    LaneHandle lane,
    double s
);
// Resolution order:
//   1. Lane-level speed limit
//   2. Road-level speed limit

9.12 Lane Material APIs

Lane Material APIs define the surface material of roads and lanes. Lane materials describe the physical surface over which vehicles travel and are primarily intended for use by simulators, physics engines, validation workflows, and export pipelines.

Lane materials: - Are semantic attributes, not geometric - May be defined at both lane and road level - May vary along s using segment-based definitions - Do not affect lane topology or geometry - Lane-level material definitions always take precedence over road-level defaults.

Road-Level Default Lane Materials

Road-level lane materials define default surface materials that apply to all lanes of a road unless explicitly overridden at lane level.

Commands
  • AddRoadMaterialSegment

    Result AddRoadMaterialSegment(
        RoadHandle road,
        LaneMaterialSegment segment
    );
    // Adds a road-level material segment starting at segment.SStart
    

  • UpdateRoadMaterialSegment

    Result UpdateRoadMaterialSegment(
        RoadHandle road,
        LaneMaterialSegment segment
    );
    // Updates an existing road-level material segment identified by SStart
    

  • RemoveRoadMaterialSegment

    Result RemoveRoadMaterialSegment(
        RoadHandle road,
        double sStart
    );
    // Removes the road-level material segment that starts at sStart
    

  • ClearRoadMaterialSegments

    Result ClearRoadMaterialSegments(
        RoadHandle road
    );
    // Removes all road-level material segments from the road
    

Queries
  • GetRoadMaterialSegments

    Result<IReadOnlyList<LaneMaterialSegment>> GetRoadMaterialSegments(
        RoadHandle road
    );
    // Returns all road-level material segments ordered by SStart
    

  • GetRoadMaterialAtS

    Result<LaneMaterialType> GetRoadMaterialAtS(
        RoadHandle road,
        double s
    );
    // Returns the road-level material active at position s
    

Lane-Level Materials

Lane-level materials define surface materials specific to a lane and override any road-level default materials.

Commands
  • AddLaneMaterialSegment

    Result AddLaneMaterialSegment(
        LaneHandle lane,
        LaneMaterialSegment segment
    );
    // Adds a lane-level material segment starting at segment.SStart
    

  • UpdateLaneMaterialSegment

    Result UpdateLaneMaterialSegment(
        LaneHandle lane,
        LaneMaterialSegment segment
    );
    // Updates an existing lane-level material segment identified by SStart
    

  • RemoveLaneMaterialSegment

    Result RemoveLaneMaterialSegment(
        LaneHandle lane,
        double sStart
    );
    // Removes the lane-level material segment that starts at sStart
    

  • ClearLaneMaterialSegments

    Result ClearLaneMaterialSegments(
        LaneHandle lane
    );
    // Removes all lane-level material segments from the lane
    

Queries
  • GetLaneMaterialSegments

    Result<IReadOnlyList<LaneMaterialSegment>> GetLaneMaterialSegments(
        LaneHandle lane
    );
    // Returns all lane-level material segments ordered by SStart
    

  • GetLaneMaterialAtS

    Result<LaneMaterialType> GetLaneMaterialAtS(
        LaneHandle lane,
        double s
    );
    // Returns the lane-level material active at position s
    

Effective Lane Material Resolution

For convenience and downstream consumers, the SDK provides a resolved query that applies precedence rules automatically.

Lane-level material definitions override road-level defaults.

Query
  • GetEffectiveLaneMaterialAtS
    Result<LaneMaterialType> GetEffectiveLaneMaterialAtS(
        LaneHandle lane,
        double s
    );
    // Resolution order:
    //   1. Lane-level material
    //   2. Road-level default material
    //   3. LaneMaterialType.Unknown if none exists
    

9.13 Tram Lane APIs

Tram Lane APIs define tram usage capabilities on lanes. Trams are modeled as a lane-dependent semantic feature, allowing lanes to support tram traffic either exclusively or in combination with regular road traffic.

Tram support: - Is defined at lane level - May vary along the lane using s-based segments - Does not introduce geometry or rail objects by itself - Is intended to be consumed by export, validation, and simulation pipelines - Tram lane definitions do not affect road or lane geometry and do not imply the presence of physical rails unless explicitly added through other APIs.


Commands

AddTramLaneSegment
Result AddTramLaneSegment(
    LaneHandle lane,
    TramLaneSegment segment
);
// Enables tram usage on the lane starting at segment.SStart
// Tram usage may be exclusive or shared depending on segment.Usage
// Multiple segments may exist on the same lane
UpdateTramLaneSegment
Result UpdateTramLaneSegment(
    LaneHandle lane,
    TramLaneSegment segment
);
// Updates the tram usage segment identified by segment.SStart
// The updated segment replaces the existing definition at that position
RemoveTramLaneSegment
Result RemoveTramLaneSegment(
    LaneHandle lane,
    double sStart
);
// Removes the tram usage segment that starts at sStart
ClearTramLaneSegments
Result ClearTramLaneSegments(
    LaneHandle lane
);
// Clears all tram usage segments defined on the lane
// After this call, the lane does not support tram traffic

Queries

GetTramLaneSegments
Result<IReadOnlyList<TramLaneSegment>> GetTramLaneSegments(
    LaneHandle lane
);
// Returns all tram usage segments ordered by SStart
GetTramUsageAtS
Result<TramUsageType> GetTramUsageAtS(
    LaneHandle lane,
    double s
);
// Returns the tram usage mode active at position s
// If no segment applies, TramUsageType.None is returned

Error handling

Tram Lane APIs return structured errors in the following cases: - Invalid lane handle - Invalid or negative s positions - Overlapping or duplicate tram usage segments - Attempting to update or remove a non-existent segment

All errors are reported using the standard Result / Result pattern and do not modify lane geometry or connectivity.


9.14 Road Structures APIs (Bridges and Tunnels)

Road Structure APIs provide explicit support for modeling bridges and tunnels as road-level semantic structures. These structures describe how a road segment interacts with its surrounding environment and infrastructure but do not define geometric shape or elevation by themselves.

Road structures:

  • Are defined at road level
  • Are segment-based along s
  • Do not modify plan-view or elevation geometry
  • Are used by export, validation, and simulation pipelines

A road segment may be classified as either a bridge, a tunnel, or neither. Bridge and tunnel segments must not overlap.

Design Principles

Road structure definitions follow these principles:

  • Structures are semantic annotations, not geometry
  • Geometry (height, slope, clearance) is handled separately
  • Structures are explicit and deterministic
  • Structure segments are non-overlapping and ordered
  • Only one structure type may be active at a given s position

These principles align directly with ASAM OpenDRIVE <bridge> and <tunnel> elements.


Bridge APIs

Bridge APIs define road segments that are structurally elevated above the surrounding terrain or other infrastructure.

Commands

AddBridgeSegment

Result AddBridgeSegment(
    RoadHandle road,
    BridgeSegment segment
);
// Adds a bridge structure segment starting at segment.SStart
// Bridge segments are road-level and segment-based

UpdateBridgeSegment

Result UpdateBridgeSegment(
    RoadHandle road,
    BridgeSegment segment
);
// Updates an existing bridge segment identified by segment.SStart

RemoveBridgeSegment

Result RemoveBridgeSegment(
    RoadHandle road,
    double sStart
);
// Removes the bridge segment that starts at sStart

ClearBridgeSegments

Result ClearBridgeSegments(
    RoadHandle road
);
// Removes all bridge segments from the road

Queries

GetBridgeSegments

Result<IReadOnlyList<BridgeSegment>> GetBridgeSegments(
    RoadHandle road
);
// Returns all bridge segments ordered by SStart

IsBridgeAtS

Result<bool> IsBridgeAtS(
    RoadHandle road,
    double s
);
// Returns true if the road is classified as a bridge at position s


Tunnel APIs

Tunnel APIs define road segments that are structurally enclosed within terrain or constructed infrastructure.

Commands

AddTunnelSegment

Result AddTunnelSegment(
    RoadHandle road,
    TunnelSegment segment
);
// Adds a tunnel structure segment starting at segment.SStart
// Tunnel segments are road-level and segment-based

UpdateTunnelSegment

Result UpdateTunnelSegment(
    RoadHandle road,
    TunnelSegment segment
);
// Updates an existing tunnel segment identified by segment.SStart

RemoveTunnelSegment

Result RemoveTunnelSegment(
    RoadHandle road,
    double sStart
);
// Removes the tunnel segment that starts at sStart

ClearTunnelSegments

Result ClearTunnelSegments(
    RoadHandle road
);
// Removes all tunnel segments from the road

Queries

GetTunnelSegments

Result<IReadOnlyList<TunnelSegment>> GetTunnelSegments(
    RoadHandle road
);
// Returns all tunnel segments ordered by SStart

IsTunnelAtS

Result<bool> IsTunnelAtS(
    RoadHandle road,
    double s
);
// Returns true if the road is classified as a tunnel at position s


Effective Road Structure Queries

For convenience and inspection, the SDK provides resolved queries that determine the active road structure at a given position.

Queries

GetRoadStructureAtS

Result<RoadStructureType> GetRoadStructureAtS(
    RoadHandle road,
    double s
);
// Returns the active road structure at position s
// Possible results: None, Bridge, Tunnel


Error Handling

Road Structure APIs return structured errors in the following cases:

  • Invalid road handle
  • Invalid or negative s positions
  • Overlapping bridge or tunnel segments
  • Attempting to overlap bridge and tunnel segments
  • Attempting to update or remove a non-existent segment

All errors are reported using the standard Result / Result pattern. No geometry is modified if an operation fails.


Usage Example

// Add a bridge segment
roadApi.AddBridgeSegment(
    road,
    new BridgeSegment
    {
        SStart = 100.0,
        Length = 50.0
    }
);

// Add a tunnel segment
roadApi.AddTunnelSegment(
    road,
    new TunnelSegment
    {
        SStart = 300.0,
        Length = 120.0
    }
);

9.15 Usage Example

var road = roadApi.CreateRoad(map, "R_Main", RoadRule.RightHandTraffic).Value;

var section = roadApi.AddLaneSection(road, 0.0).Value;

var lane = roadApi.AddLane(
    section,
    LaneSide.Right,
    -1,
    LaneType.Driving
).Value;

roadApi.AddLaneWidthSegment(
    lane,
    0.0,
    new WidthPolynomial { A = 3.5 }
);

Usage Example — GetLaneConnectivityGraph

This example demonstrates how to use the lane connectivity graph to inspect inter-lane topology across several roads.

Scenario

We create: - 3 roads - 1 lane per road - Explicit successor/predecessor connectivity

Then, we retrieve and inspect the lane connectivity graph.

Step 1: Create roads and lanes

var roadA = roadApi.CreateRoad(map, "R_A", RoadRule.RightHandTraffic).Value;
var roadB = roadApi.CreateRoad(map, "R_B", RoadRule.RightHandTraffic).Value;
var roadC = roadApi.CreateRoad(map, "R_C", RoadRule.RightHandTraffic).Value;

var secA = roadApi.AddLaneSection(roadA, 0.0).Value;
var secB = roadApi.AddLaneSection(roadB, 0.0).Value;
var secC = roadApi.AddLaneSection(roadC, 0.0).Value;

var laneA = roadApi.AddLane(secA, LaneSide.Right, -1, LaneType.Driving).Value;
var laneB = roadApi.AddLane(secB, LaneSide.Right, -1, LaneType.Driving).Value;
var laneC = roadApi.AddLane(secC, LaneSide.Right, -1, LaneType.Driving).Value;

Step 2: Define lane connectivity

roadApi.SetLaneSuccessor(laneA, laneB);
roadApi.SetLaneSuccessor(laneB, laneC);
// This represents: laneA → laneB → laneC

Step 3: Retrieve the lane connectivity graph

var graphResult = roadApi.GetLaneConnectivityGraph();
if (!graphResult.IsSuccess)
{
    HandleError(graphResult.Error);
}
var graph = graphResult.Value;

Step 4: Inspect the graph (adjacency-style)

foreach (var node in graph.Lanes)
{
    var lane = node.Lane;

    Console.WriteLine($"Lane: {lane}");

    foreach (var successor in node.Successors)
    {
        Console.WriteLine($"  -> Successor: {successor}");
    }

    foreach (var predecessor in node.Predecessors)
    {
        Console.WriteLine($"  <- Predecessor: {predecessor}");
    }
}

Conceptual graph structure (simplified) - Lane A: Successors: [Lane B], Predecessors: [] - Lane B: Successors: [Lane C], Predecessors: [Lane A] - Lane C: Successors: [], Predecessors: [Lane B]

What this graph is useful for - Routing and reachability analysis - Detecting broken or missing lane links - Validation and debugging - Visualization and tooling - Simulation preparation


Summary

The Road and Lane APIs provide full control over the structural and topological components of an OpenDRIVE map. These APIs are central to Replimap’s authoring capabilities and are used by most higher-level workflows, including junction creation, validation, and simulation preparation.


10. Junction APIs

The Junction APIs provide functionality for modeling complex connectivity between roads in an OpenDRIVE map. Junctions define how multiple roads intersect and how lanes connect across those intersections.

This module builds on the Road, Lane, and Geometry APIs and is essential for creating navigable and simulation-ready road networks.


10.1 Overview

The Junction APIs allow applications to:

  • Create and delete junctions
  • Associate roads with junctions
  • Define lane-to-lane connections within junctions
  • Manage contact points and priorities
  • Automatically generate or repair junction structures
  • Inspect junction topology and connectivity

All junction operations are explicit and deterministic.


10.2 Public Types

struct JunctionHandle { }
struct JunctionConnectionHandle { }

enum ContactPoint
{
    Start,
    End
}

enum JunctionType
{
    Default,
    Priority,
    Roundabout,
    Direct
}

10.3 Junction Management APIs

Commands

CreateJunction

Creates a new junction.

Result<JunctionHandle> CreateJunction(
    string junctionId,
    JunctionType type
);

Result<JunctionHandle> CreateJunction(
    MapHandle map,
    string junctionId,
    JunctionType type
);
Errors - DuplicateJunctionId - InvalidJunctionType

Example

var junction = junctionApi
    .CreateJunction("J1", JunctionType.Default)
    .Value;

// Target a specific map without changing the active map
var junctionInMapB = junctionApi
    .CreateJunction(mapB, "J2", JunctionType.Default)
    .Value;

DeleteJunction

Result DeleteJunction(JunctionHandle junction);

RenameJunction

Result RenameJunction(
    JunctionHandle junction,
    string newJunctionId
);

SetJunctionType

Result SetJunctionType(
    JunctionHandle junction,
    JunctionType type
);

Queries

GetJunctionById

Result<JunctionHandle> GetJunctionById(string junctionId);

GetAllJunctions

Result<IReadOnlyList<JunctionHandle>> GetAllJunctions();

GetJunctionType

Result<JunctionType> GetJunctionType(JunctionHandle junction);


10.4 Junction Connection APIs

Junction connections define how a road connects to a junction and how traffic flows through it.

Commands

AddRoadToJunction

Associates a road with a junction.

Result<JunctionConnectionHandle> AddRoadToJunction(
    JunctionHandle junction,
    RoadHandle road,
    ContactPoint contactPoint
);

RemoveRoadFromJunction

Result RemoveRoadFromJunction(
    JunctionHandle junction,
    RoadHandle road
);

SetConnectionPriority

Result SetConnectionPriority(
    JunctionConnectionHandle connection,
    int priority
);

Queries

GetJunctionConnections

Result<IReadOnlyList<JunctionConnectionHandle>> GetJunctionConnections(
    JunctionHandle junction
);

GetConnectedRoads

Result<IReadOnlyList<RoadHandle>> GetConnectedRoads(
    JunctionHandle junction
);


10.5 Lane-to-Lane Linking APIs

Lane-to-lane links define the navigable paths through a junction.

Commands

AddLaneLink

Result AddLaneLink(
    JunctionHandle junction,
    LaneHandle fromLane,
    LaneHandle toLane
);

RemoveLaneLink

Result RemoveLaneLink(
    JunctionHandle junction,
    LaneHandle fromLane,
    LaneHandle toLane
);

ClearLaneLinks

Result ClearLaneLinks(JunctionHandle junction);

Queries

GetLaneLinks

Result<IReadOnlyList<LaneLink>> GetLaneLinks(
    JunctionHandle junction
);

GetSuccessorLanesThroughJunction

Result<IReadOnlyList<LaneHandle>> GetSuccessorLanesThroughJunction(
    LaneHandle lane
);


10.6 Automatic Junction Utilities

Commands

AutoGenerateJunctionConnections

Automatically generates junction connections based on road and lane topology.

Result AutoGenerateJunctionConnections(
    JunctionHandle junction
);

RebuildJunction

Recomputes all internal junction connectivity.

Result RebuildJunction(JunctionHandle junction);

RepairJunctionConnectivity

Attempts to fix invalid or incomplete lane links.

Result RepairJunctionConnectivity(
    JunctionHandle junction
);

10.7 Junction Validation Queries

Queries

ValidateJunction

Result<JunctionValidationReport> ValidateJunction(
    JunctionHandle junction
);

GetJunctionConnectivityGraph

Result<JunctionConnectivityGraph> GetJunctionConnectivityGraph(
    JunctionHandle junction
);


10.8 Junction Transformation APIs

Junction Transformation APIs provide high-level, procedural operations for modifying junction geometry and topology in a controlled and deterministic manner. These operations encapsulate complex, multi-step algorithms that operate across multiple roads, lanes, and geometry elements associated with a junction.

Junction transformations are intended to:

  • Improve geometric quality and continuity
  • Normalize junction structure
  • Prepare junctions for simulation, validation, or export

These APIs operate at junction scope and must not be confused with low-level geometry editing commands.

Design Principles

Junction transformation operations follow these principles:

  • Operate on an entire junction as a single unit
  • May modify geometry, elevation, lane widths, and connectivity as required
  • Are deterministic given the same inputs and options
  • Expose intent through explicit, named operations
  • Do not expose internal algorithmic steps

All transformations are executed explicitly via command APIs.

Junction Smoothing

Junction smoothing improves geometric continuity by reducing sharp curvature, heading discontinuities, and abrupt transitions between incoming and outgoing roads.

Commands

SmoothJunction

Result SmoothJunction(
    JunctionHandle junction,
    JunctionSmoothingOptions options
);
// Smooths geometric transitions within the junction
// Adjusts plan-view geometry to reduce curvature and heading discontinuities
// May modify connected road geometry within junction influence area

JunctionSmoothingOptions

struct JunctionSmoothingOptions
{
    double InfluenceRadius;        // Distance from junction center affected by smoothing
    double MaxCurvature;           // Maximum allowed curvature after smoothing
    bool PreserveLaneCount;        // Ensures lane counts are preserved
}

Junction Flattening

Junction flattening removes vertical variation within a junction to produce a level intersection area.

This operation is commonly used to:

  • Remove elevation noise
  • Simplify junctions for simulators
  • Ensure consistent vertical alignment

Commands

FlattenJunction

Result FlattenJunction(
    JunctionHandle junction,
    JunctionFlatteningOptions options
);
// Removes elevation, superelevation, and lane height variation within the junction
// Produces a vertically flat junction area

JunctionFlatteningOptions

struct JunctionFlatteningOptions
{
    double Elevation;              // Target elevation for the junction
    bool PreserveApproachSlopes;   // Preserves elevation slopes outside the junction
}

Junction Equalization

Junction equalization normalizes lane and geometry attributes across junction connections to improve consistency and symmetry.

This operation may adjust:

  • Lane widths
  • Lane offsets
  • Geometry lengths
  • Connection alignment

Commands

EqualizeJunction

Result EqualizeJunction(
    JunctionHandle junction,
    JunctionEqualizationOptions options
);
// Normalizes lane and geometry properties across junction connections
// Ensures consistent widths and alignment where possible

JunctionEqualizationOptions

struct JunctionEqualizationOptions
{
    bool EqualizeLaneWidths;       // Normalizes lane widths across connections
    bool EqualizeOffsets;          // Normalizes lateral offsets
    bool EqualizeGeometryLengths;  // Normalizes connection geometry lengths
}

Queries

Junction Transformation APIs are command-only operations.

No query APIs are provided, as transformations directly modify junction state.

Inspection of results should be performed using existing:

  • Geometry APIs
  • Lane APIs
  • Junction inspection queries

Error Handling

Junction transformation APIs return structured errors in the following cases:

  • Invalid junction handle
  • Junction is not editable
  • Junction geometry is incomplete or inconsistent
  • Transformation constraints cannot be satisfied with the provided options

All errors are reported using the standard Result pattern. No partial transformations are applied if an operation fails.

Usage Example

// Smooth and flatten a junction
junctionApi.SmoothJunction(
    junction,
    new JunctionSmoothingOptions
    {
        InfluenceRadius = 30.0,
        MaxCurvature = 0.02,
        PreserveLaneCount = true
    }
);

junctionApi.FlattenJunction(
    junction,
    new JunctionFlatteningOptions
    {
        Elevation = 0.0,
        PreserveApproachSlopes = true
    }
);

10.9 Usage Example

var junction = junctionApi
    .CreateJunction("J_Main", JunctionType.Default)
    .Value;

junctionApi.AddRoadToJunction(
    junction,
    roadA,
    ContactPoint.End
);

junctionApi.AddRoadToJunction(
    junction,
    roadB,
    ContactPoint.Start
);

junctionApi.AutoGenerateJunctionConnections(junction);

Usage Example — GetJunctionConnectivityGraph

This example demonstrates how to use the junction connectivity graph to inspect lane-level connections through a junction.

Scenario

We model a simple 4-way intersection: - Two roads crossing: - North–South road - East–West road - One driving lane per road - Straight-through movements only

We then inspect the junction connectivity graph to understand how lanes are connected through the junction.

Step 1: Create roads and lanes

var roadNS = roadApi.CreateRoad(map, "R_NS", RoadRule.RightHandTraffic).Value;
var roadEW = roadApi.CreateRoad(map, "R_EW", RoadRule.RightHandTraffic).Value;

var secNS = roadApi.AddLaneSection(roadNS, 0.0).Value;
var secEW = roadApi.AddLaneSection(roadEW, 0.0).Value;

var laneNS = roadApi.AddLane(secNS, LaneSide.Right, -1, LaneType.Driving).Value;
var laneEW = roadApi.AddLane(secEW, LaneSide.Right, -1, LaneType.Driving).Value;

Step 2: Create a junction

var junction = junctionApi
    .CreateJunction("J_Main", JunctionType.Default)
    .Value;

Step 3: Attach roads to the junction

junctionApi.AddRoadToJunction(
    junction,
    roadNS,
    ContactPoint.End
);

junctionApi.AddRoadToJunction(
    junction,
    roadEW,
    ContactPoint.Start
);

Step 4: Define lane-to-lane connectivity

junctionApi.AddLaneLink(
    junction,
    laneNS,
    laneEW
);

junctionApi.AddLaneLink(
    junction,
    laneEW,
    laneNS
);

This encodes: - NS → EW (straight movement) - EW → NS (straight movement)

Step 5: Retrieve the junction connectivity graph

var graphResult = junctionApi.GetJunctionConnectivityGraph(junction);
if (!graphResult.IsSuccess)
{
    HandleError(graphResult.Error);
}

var graph = graphResult.Value;

Step 6: Inspect the graph

foreach (var entry in graph.Connections)
{
    Console.WriteLine(
        $"From lane {entry.FromLane} → To lane {entry.ToLane}"
    );
}

Conceptual example output:

Lane R_NS:-1 → Lane R_EW:-1
Lane R_EW:-1 → Lane R_NS:-1

What this graph represents: - Directed connectivity inside the junction - All legal lane-to-lane movements - Independent of linear predecessor/successor links


Summary

The Junction APIs provide explicit and fine-grained control over how roads and lanes intersect and connect. These APIs are critical for building realistic and navigable OpenDRIVE maps and are commonly used alongside Road, Lane, and Validation APIs.

11. Objects, Signals, and Controllers APIs

The Objects, Signals, and Controllers APIs provide functionality for modeling roadside infrastructure and traffic control elements in an OpenDRIVE map. These APIs allow applications to add, modify, query, and manage static and dynamic elements associated with roads and lanes.

This module is essential for enriching road networks with real-world context and traffic behavior information.


11.1 Overview

This module enables applications to:

  • Create and manage OpenDRIVE objects
  • Define parametric and repeated objects
  • Model roadside infrastructure such as guardrails, barriers, trees, buildings, and obstacles
  • Create and manage traffic signals
  • Define signal dependencies and validity ranges
  • Create and configure traffic signal controllers and phases

All objects and signals are positioned relative to roads or lanes using OpenDRIVE’s coordinate conventions.


11.2 Public Types

struct ObjectHandle { }
struct SignalHandle { }
struct ControllerHandle { }

enum ObjectType
{
    GuardRail,
    Barrier,
    Pole,
    Tree,
    Building,
    Obstacle,
    Tunnel,
    Bridge,
    Custom
}

enum SignalType
{
    Static,
    Dynamic
}

enum Orientation
{
    Positive,
    Negative,
    Both
}


enum AttachmentAlignment
{
    None,
    AlignWithRoad,
    AlignWithLane,
    FaceTraffic,
    FaceOppositeTraffic
}
// Defines how the object orientation is aligned relative to the host

enum AttachmentUpdateMode
{
    Static,
    ResnapOnGeometry,
    AlwaysFollowHost
}
// Defines how the object reacts to host geometry changes

struct AttachmentReference
{
    double SOffset;
    double LateralOffset;
    double HeightOffset;
}
// Defines the object anchor point in host-relative coordinates

struct ObjectAttachmentOptions
{
    AttachmentReference Reference;
    AttachmentAlignment Alignment;
    AttachmentUpdateMode UpdateMode;
}
// Defines attachment behavior, alignment, and update policy

enum ObjectAttachmentHostType
{
    None,
    Road,
    Lane
}
// Identifies the type of host entity the object is attached to

struct ObjectAttachmentInfo
{
    ObjectAttachmentHostType HostType;
    RoadHandle Road;
    LaneHandle Lane;
    ObjectAttachmentOptions Options;
}
// Describes the attachment relationship of an object
// Only one of Road or Lane is valid based on HostType

11.3 Object APIs

Commands

AddObject
Adds a new object to a road.

Result<ObjectHandle> AddObject(
    RoadHandle road,
    ObjectType type,
    double s,
    double t
);

Errors - InvalidRoadHandle - InvalidObjectType - InvalidPosition

RemoveObject

Result RemoveObject(ObjectHandle obj);

UpdateObjectPosition

Result UpdateObjectPosition(
    ObjectHandle obj,
    double s,
    double t,
    double z
);

SetObjectOrientation

Result SetObjectOrientation(
    ObjectHandle obj,
    double heading,
    double pitch,
    double roll
);

SetObjectRepeat
Defines repetition rules for an object.

Result SetObjectRepeat(
    ObjectHandle obj,
    double sStart,
    double sEnd,
    double distance
);

SetObjectOutline

Result SetObjectOutline(
    ObjectHandle obj,
    ObjectOutline outline
);

Queries

GetObjectById

Result<ObjectHandle> GetObjectById(string objectId);

GetObjectsOnRoad

Result<IReadOnlyList<ObjectHandle>> GetObjectsOnRoad(
    RoadHandle road
);

GetObjectPosition

Result<ObjectPosition> GetObjectPosition(
    ObjectHandle obj
);


11.4 Signal APIs

Commands

AddSignal
Adds a traffic signal to a road.

Result<SignalHandle> AddSignal(
    RoadHandle road,
    double s,
    double t,
    SignalType type
);

RemoveSignal

Result RemoveSignal(SignalHandle signal);

SetSignalOrientation

Result SetSignalOrientation(
    SignalHandle signal,
    Orientation orientation
);

SetSignalValidity

Result SetSignalValidity(
    SignalHandle signal,
    double sStart,
    double sEnd
);

AddSignalDependency

Result AddSignalDependency(
    SignalHandle signal,
    SignalHandle dependentSignal
);

Queries

GetSignalsOnRoad

Result<IReadOnlyList<SignalHandle>> GetSignalsOnRoad(
    RoadHandle road
);

GetSignalPosition

Result<SignalPosition> GetSignalPosition(
    SignalHandle signal
);

GetSignalDependencies

Result<IReadOnlyList<SignalHandle>> GetSignalDependencies(
    SignalHandle signal
);


11.5 Controller APIs

Commands

CreateController
Creates a new traffic signal controller.

Result<ControllerHandle> CreateController(
    string controllerId
);

Result<ControllerHandle> CreateController(
    MapHandle map,
    string controllerId
);

DeleteController

Result DeleteController(ControllerHandle controller);

AssignSignalToController

Result AssignSignalToController(
    ControllerHandle controller,
    SignalHandle signal
);

AddControllerPhase
Adds a phase definition to a controller.

Result AddControllerPhase(
    ControllerHandle controller,
    ControllerPhase phase
);

Queries

GetControllerById

Result<ControllerHandle> GetControllerById(
    string controllerId
);

GetControllerSignals

Result<IReadOnlyList<SignalHandle>> GetControllerSignals(
    ControllerHandle controller
);

GetControllerPhases

Result<IReadOnlyList<ControllerPhase>> GetControllerPhases(
    ControllerHandle controller
);


11.6 Object and Signal Catalog APIs

The Object and Signal Catalog APIs expose a read-only catalog of predefined objects and signals bundled with the SDK. These catalog entries represent standard, reusable assets such as road markings, traffic signs, barriers, poles, and other commonly used roadside elements.

The catalog is intended to:

  • Improve discoverability of available objects and signals
  • Enable consistent reuse of standard assets
  • Simplify creation of road markings and traffic elements
  • Avoid hardcoding object definitions in client applications

Catalog entries are immutable and versioned with the SDK.

Design Principles

The catalog APIs follow these principles:

  • Catalog entries are read-only
  • Each entry has a stable, unique identifier
  • Entries expose metadata only, not rendering logic
  • Catalog content is independent of any UI framework
  • Object and signal instances are created separately using existing APIs

Object Catalog Queries

GetObjectCatalog

Returns all available object catalog entries.

Result<IReadOnlyList<ObjectCatalogItem>> GetObjectCatalog();
// Returns all predefined object catalog items
// Includes road markings, barriers, poles, and other standard objects

GetObjectCatalogItem

Returns a specific object catalog entry.

Result<ObjectCatalogItem> GetObjectCatalogItem(
    string catalogId
);
// Returns metadata for the specified object catalog identifier

GetObjectCatalogByCategory

Returns object catalog entries filtered by category.

Result<IReadOnlyList<ObjectCatalogItem>> GetObjectCatalogByCategory(
    ObjectCatalogCategory category
);
// Returns all object catalog items belonging to the given category

Signal Catalog Queries

GetSignalCatalog

Returns all available signal catalog entries.

Result<IReadOnlyList<SignalCatalogItem>> GetSignalCatalog();
// Returns all predefined signal catalog items

GetSignalCatalogItem

Returns a specific signal catalog entry.

Result<SignalCatalogItem> GetSignalCatalogItem(
    string catalogId
);
// Returns metadata for the specified signal catalog identifier

Creating Objects and Signals from the Catalog

Catalog entries may be instantiated as regular objects or signals using the existing creation APIs.

CreateObjectFromCatalog

Result<ObjectHandle> CreateObjectFromCatalog(
    MapHandle map,
    string catalogId,
    ObjectPlacement placement
);
// Creates an object instance from a catalog entry
// Placement defines road or lane attachment and offsets

CreateSignalFromCatalog

Result<SignalHandle> CreateSignalFromCatalog(
    MapHandle map,
    string catalogId,
    SignalPlacement placement
);
// Creates a signal instance from a catalog entry

11.7 Object and Signal Preview APIs

The Object and Signal Preview APIs provide lightweight preview descriptors for catalog entries. These previews are intended to support UI visualization, inspection, and placement workflows without introducing rendering or graphics dependencies into the SDK.

Previews describe shape and spatial characteristics, not visual appearance.

Design Principles

Preview APIs follow these principles:

  • No rendering or drawing logic
  • No images or textures required
  • Geometry-only descriptors
  • Deterministic and lightweight
  • Optional for client usage

Object Preview Queries

GetObjectPreview

Returns a preview descriptor for an object catalog entry.

Result<ObjectPreview> GetObjectPreview(
    string catalogId
);
// Returns a geometric preview of the object
// Includes footprint, bounding box, and orientation hints

Signal Preview Queries

GetSignalPreview

Returns a preview descriptor for a signal catalog entry.

Result<SignalPreview> GetSignalPreview(
    string catalogId
);
// Returns a geometric preview of the signal
// Intended for placement and inspection workflows

Preview Descriptor Semantics

Preview descriptors may include:

  • Axis-aligned bounding boxes
  • 2D footprints
  • Reference orientation and pivot point
  • Nominal dimensions

Preview data:

  • Is independent of scale and styling
  • Must not be interpreted as final visual appearance
  • Is suitable for editor previews and snapping logic

11.8 Object Attachment and Snapping APIs

Object Attachment and Snapping APIs define semantic attachment relationships between objects (including signals, road marks, poles, and other roadside assets) and host entities such as roads and lanes.

Attachment relationships ensure that objects remain correctly positioned and oriented relative to their host when geometry or topology changes occur. These APIs are backend-safe and UI-agnostic.

Commands

AttachObjectToRoad

Result AttachObjectToRoad(
    ObjectHandle object,
    RoadHandle road,
    ObjectAttachmentOptions options
);
// Attaches an object to a road using host-relative placement rules
// The object position is stored relative to the road reference line
// Attachment behavior is controlled by the provided options

AttachObjectToLane

Result AttachObjectToLane(
    ObjectHandle object,
    LaneHandle lane,
    ObjectAttachmentOptions options
);
// Attaches an object to a lane using lane-relative placement rules
// Overrides any existing attachment

DetachObject

Result DetachObject(
    ObjectHandle object
);
// Removes any existing attachment from the object
// The object remains at its current world position

ResnapObject

Result ResnapObject(
    ObjectHandle object
);
// Recomputes the object placement based on its attachment definition
// Does not modify attachment options

UpdateObjectAttachment

Result UpdateObjectAttachment(
    ObjectHandle object,
    ObjectAttachmentOptions options
);
// Updates the attachment options of an already attached object
// Does not change the attachment host
Queries

GetObjectAttachment

Result<ObjectAttachmentInfo> GetObjectAttachment(
    ObjectHandle object
);
// Returns attachment information for the object
// Includes host reference and attachment options

IsObjectAttached

Result<bool> IsObjectAttached(
    ObjectHandle object
);
// Returns true if the object has an active attachment

GetAttachedObjectsForRoad

Result<IReadOnlyList<ObjectHandle>> GetAttachedObjectsForRoad(
    RoadHandle road
);
// Returns all objects currently attached to the specified road

GetAttachedObjectsForLane

Result<IReadOnlyList<ObjectHandle>> GetAttachedObjectsForLane(
    LaneHandle lane
);
// Returns all objects currently attached to the specified lane
Summary

The Object Attachment and Snapping APIs provide a robust and explicit mechanism for defining host-relative object behavior. By separating attachment semantics from placement and geometry, the SDK enables stable snap-and-adjust workflows, automation, and editor tooling without introducing UI dependencies.


11.9 Usage Example

var obj = objectApi.AddObject(
    road,
    ObjectType.GuardRail,
    s: 10.0,
    t: -2.0
).Value;

var signal = signalApi.AddSignal(
    road,
    s: 25.0,
    t: -1.5,
    SignalType.Dynamic
).Value;

var controller = controllerApi.CreateController("C1").Value;
controllerApi.AssignSignalToController(controller, signal);

// Target a specific map without changing the active map
var controllerInMapB = controllerApi.CreateController(mapB, "C2").Value;

Summary

The Objects, Signals, and Controllers APIs enable detailed modeling of roadside infrastructure and traffic control systems. These APIs are commonly used to enrich road networks for simulation, validation, and visualization workflows, and they integrate closely with the Road, Lane, and Junction APIs.


12. Rail Network APIs

The Rail Network APIs provide support for modeling railroad infrastructure as an independent transportation network. Railroads are not represented as roads or lanes and do not share road-based topology, geometry, or traffic rules.

Rail networks are modeled as a separate graph with their own tracks, connectivity, and interaction points with the road network.

12.1 Design Principles

Rail networks follow these core principles:

  • Railroads are not lanes
  • Railroads do not use road reference lines
  • Rail topology is independent from road topology
  • Road–rail interaction occurs only through explicit crossings
  • Rail APIs do not modify road or lane geometry

12.2 Public Data Types

Rail Track Direction

enum RailDirection
{
    Bidirectional,
    ForwardOnly,
    ReverseOnly
}

Rail Track Type

enum RailTrackType
{
    MainLine,
    BranchLine,
    Yard,
    Siding,
    Depot,
    Industrial
}

Rail Track Definition

struct RailTrackDefinition
{
    string Id;
    RailTrackType Type;
    RailDirection Direction;
}

Rail Track Segment

struct RailTrackSegment
{
    double Length;
}

Road–Rail Crossing Type

enum RoadRailCrossingType
{
    LevelCrossing,
    Bridge,
    Tunnel
}

Road–Rail Crossing Definition

struct RoadRailCrossingDefinition
{
    RoadRailCrossingType Type;
    double RoadS;
}

12.3 Rail Track APIs

Rail tracks represent linear infrastructure elements forming the nodes of the rail network.

Commands

AddRailTrack

Result<RailTrackHandle> AddRailTrack(
    RailTrackDefinition definition
);
// Creates a new rail track in the rail network
// Track identifiers must be unique within the session

RemoveRailTrack

Result RemoveRailTrack(
    RailTrackHandle track
);
// Removes the rail track and all associated rail connections

Queries

GetRailTracks

Result<IReadOnlyList<RailTrackHandle>> GetRailTracks();
// Returns all rail tracks defined in the current session

GetRailTrackDefinition

Result<RailTrackDefinition> GetRailTrackDefinition(
    RailTrackHandle track
);
// Returns metadata associated with the specified rail track

12.4 Rail Connectivity APIs

Rail connectivity defines how rail tracks are linked together to form a navigable rail network.

Commands

ConnectRailTracks

Result ConnectRailTracks(
    RailTrackHandle from,
    RailTrackHandle to
);
// Creates a directional connection between two rail tracks
// Direction constraints are enforced based on track definitions

DisconnectRailTracks

Result DisconnectRailTracks(
    RailTrackHandle from,
    RailTrackHandle to
);
// Removes an existing rail connection

Queries

GetRailConnectivityGraph

Result<RailNetworkGraph> GetRailConnectivityGraph();
// Returns the rail network connectivity graph

12.5 Road–Rail Crossing APIs

Road–rail crossings define explicit interaction points between road and rail networks.

Crossings do not merge road and rail topology and are represented as standalone interaction entities.

Commands

AddRoadRailCrossing

Result<RoadRailCrossingHandle> AddRoadRailCrossing(
    RoadHandle road,
    RailTrackHandle track,
    RoadRailCrossingDefinition definition
);
// Creates a road–rail crossing at the specified road position
// Does not modify road or rail topology

RemoveRoadRailCrossing

Result RemoveRoadRailCrossing(
    RoadRailCrossingHandle crossing
);
// Removes the specified road–rail crossing

Queries

GetRoadRailCrossings

Result<IReadOnlyList<RoadRailCrossingHandle>> GetRoadRailCrossings();
// Returns all defined road–rail crossings

12.6 Rail and Road Interaction Queries

Queries

GetRailTracksAtRoad

Result<IReadOnlyList<RailTrackHandle>> GetRailTracksAtRoad(
    RoadHandle road
);
// Returns rail tracks that intersect the specified road

GetRoadsCrossedByRail

Result<IReadOnlyList<RoadHandle>> GetRoadsCrossedByRail(
    RailTrackHandle track
);
// Returns all roads intersected by the specified rail track

12.7 Error Handling

Rail Network APIs return structured errors in the following cases:

  • Duplicate rail track identifiers
  • Invalid rail track or crossing handles
  • Invalid road handles
  • Incompatible or invalid rail connections
  • Attempting to remove non-existent tracks or crossings

All errors are reported using the standard Result / Result pattern and do not affect road or lane geometry.

12.8 Usage Example

// Create a rail track
var track = railApi.AddRailTrack(new RailTrackDefinition
{
    Id = "Rail_01",
    Type = RailTrackType.MainLine,
    Direction = RailDirection.Bidirectional
}).Value;

// Connect tracks
railApi.ConnectRailTracks(trackA, trackB);

// Add a road–rail crossing
railApi.AddRoadRailCrossing(
    road,
    track,
    new RoadRailCrossingDefinition
    {
        Type = RoadRailCrossingType.LevelCrossing,
        RoadS = 120.0
    }
);

Summary

The Rail Network APIs model railroad infrastructure as a first-class, independent domain within the SDK. By keeping rail topology separate from road and lane semantics, the SDK preserves architectural clarity while enabling accurate multimodal and road–rail interaction workflows.


13. Validation APIs (XODR Validator)

The Validation APIs provide comprehensive mechanisms for verifying the structural correctness, semantic consistency, and specification compliance of OpenDRIVE (XODR) maps. These APIs support both fine-grained validation checks and full black-box validation workflows, making them suitable for interactive editing, automated QA pipelines, and large-scale batch processing.

The validation system combines:

  • ASAM OpenDRIVE rule validation
  • Custom and extended rules
  • Structural and topological analysis
  • Geometry and attribute consistency checks

Validation can be executed synchronously for fast checks or asynchronously for long-running, full-map analysis.


13.1 Overview of Validation Capabilities

The XODR Validator can be used to:

  • Validate a full OpenDRIVE map against ASAM specifications
  • Validate subsets of a map (roads, lanes, junctions)
  • Perform deep structural analysis without modifying the map
  • Detect geometry, topology, and connectivity issues
  • Identify violations with precise location context
  • Generate structured, machine-readable validation reports
  • Run validation in blocking or non-blocking (async) mode

The validator operates independently of any UI and is safe to use in headless environments.


13.2 Validation Scope and Categories

Validation checks are grouped into logical categories:

  • Structural Validation
  • Road and lane hierarchy correctness
  • Presence of required OpenDRIVE elements
  • Valid ID references and cross-links
  • Duplicate or missing identifiers

  • Geometry Validation

  • Plan-view continuity
  • Overlapping or disconnected geometry
  • Invalid curvature or polynomial definitions
  • Degenerate or zero-length segments

  • Elevation and Profile Validation

  • Elevation continuity
  • Superelevation correctness
  • Lateral shape consistency
  • Physically implausible slopes or banking

  • Lane and Topology Validation

  • Lane section ordering
  • Lane ID consistency
  • Lane width and border continuity
  • Lane predecessor/successor correctness
  • Missing or invalid lane links

  • Junction Validation

  • Road–junction associations
  • Lane-to-lane connectivity through junctions
  • Contact point correctness
  • Priority and rule consistency

  • Object and Signal Validation

  • Object placement validity
  • Signal orientation and range checks
  • Signal dependency cycles
  • Controller–signal consistency

  • Semantic and Rule-Based Validation

  • ASAM OpenDRIVE rule compliance
  • Country- or project-specific custom rules
  • Unsupported or deprecated attribute usage

13.3 Validation Reports

All validation operations produce a Validation Report, which is a structured result containing:

  • Validation status (Passed / Failed / Warnings)
  • List of detected issues
  • Severity classification:
  • Info
  • Warning
  • Error
  • Fatal
  • Rule or check identifier
  • Affected element (road, lane, junction, object, signal)
  • Location context (road ID, lane ID, s range)
  • Human-readable description
  • Optional auto-fix suggestions (when available)

Validation reports are deterministic and suitable for automated comparison and auditing.


13.4 Synchronous Validation APIs

Synchronous validation APIs are intended for:

  • Interactive editing
  • Small or medium-sized maps
  • Quick correctness checks
  • Immediate feedback scenarios

These calls block until validation completes.

ValidateMap
Validates the entire map synchronously.

Result<ValidationReport> ValidateMap(
    MapHandle map
);

ValidateRoad

Result<ValidationReport> ValidateRoad(
    RoadHandle road
);

ValidateLaneSection

Result<ValidationReport> ValidateLaneSection(
    LaneSectionHandle laneSection
);

ValidateJunction

Result<ValidationReport> ValidateJunction(
    JunctionHandle junction
);

ValidateObjectsAndSignals

Result<ValidationReport> ValidateObjectsAndSignals(
    MapHandle map
);

When to Use Synchronous Validation

Use synchronous validation when:

  • The expected execution time is short
  • Validation is triggered by a user action
  • Immediate results are required
  • Blocking the calling thread is acceptable

13.5 Asynchronous Validation APIs

Asynchronous validation APIs are designed for:

  • Large or complex maps
  • Full black-box validation
  • Batch and CI/CD pipelines
  • Background processing without blocking the main thread

Asynchronous APIs return a JobHandle that represents the running validation task.

ValidateMapAsync (Black-Box Validation)
Performs a full, deep validation of the map in the background.

JobHandle<ValidationReport> ValidateMapAsync(
    MapHandle map,
    ValidationOptions options
);
This method:

  • Performs all structural, geometric, and semantic checks
  • Does not modify the map
  • Can run for extended durations
  • Is safe for headless execution

ValidateXodrFileAsync
Validates an XODR file without loading it into an editable map.

JobHandle<ValidationReport> ValidateXodrFileAsync(
    string xodrFilePath,
    ValidationOptions options
);
This is a true black-box analysis and is ideal for:

  • External file validation
  • Regression testing
  • CI pipelines
  • Third-party data verification

13.6 JobHandle and Async Workflow

All asynchronous validation methods return a JobHandle<T>.

A job handle provides full control over the lifecycle of the validation task.

Job Status

JobStatus GetStatus();

Possible statuses:

  • Pending
  • Running
  • Completed
  • Failed
  • Cancelled

Progress Reporting

double GetProgress();
- Progress is reported as a value between 0.0 and 1.0 - Progress updates are deterministic and monotonic - Not all validation jobs report fine-grained progress; consult API notes

Completion and Result Retrieval

bool IsCompleted();
Result<ValidationReport> GetResult();
- GetResult() is only valid once the job has completed.

Awaiting Completion (Async/Await)

var report = await validator
    .ValidateMapAsync(map, options)
    .AwaitCompletionAsync();
This pattern integrates cleanly with modern .NET async workflows.

Cancellation

Result Cancel();
- Cancellation is cooperative - Partial results may be discarded - Cancelled jobs report a distinct status


13.7 Validation Options and Configuration

Validation behavior can be customized using ValidationOptions, including:

  • Enable or disable specific rule groups
  • Set severity thresholds
  • Enable strict or relaxed modes
  • Include or exclude custom rules
  • Control performance vs thoroughness trade-offs

These options allow the same API to be used for both interactive validation and strict automated QA.


Interactive Editing - Use synchronous validation on affected elements - Validate incrementally (road, lane section, junction) - Surface warnings without blocking user flow

Batch Processing / CI - Use asynchronous black-box validation - Validate full maps or files - Store and compare validation reports - Fail pipelines on error or fatal severity

Client Integration - Expose progress and status via job handles - Allow cancellation - Log full reports for traceability


Summary

The Validation APIs provide a robust, flexible, and scalable foundation for ensuring OpenDRIVE map correctness. By supporting both synchronous and asynchronous workflows, fine-grained checks and full black-box analysis, the Replimap SDK enables validation to be integrated seamlessly into interactive tools, automated pipelines, and enterprise QA systems.

14. HERE2ODR APIs

The HERE2ODR APIs provide functionality for converting HERE HD map data into ASAM OpenDRIVE (XODR) format. This module supports multiple data ingestion and conversion workflows and is designed for asynchronous execution, as operations may involve network access, large data downloads, and intensive processing.

All HERE2ODR operations are deterministic and suitable for interactive tools, headless batch pipelines, and CI/CD environments.


14.1 Overview

The HERE2ODR module enables applications to:

  • Download HERE HD map data and tiles
  • Convert HERE data into OpenDRIVE maps
  • Perform selective conversion based on area, route, or path
  • Process offline or pre-encoded HERE HDLM data
  • Generate XODR outputs suitable for editing, validation, or simulation

All conversion workflows are exposed as non-blocking asynchronous jobs.


14.2 Credential Groups and Configuration

HERE2ODR requires credentials for two distinct HERE services. These credentials are logically separated and must be provided explicitly by the integrating application.

14.2.1 HERE Maps API Credentials (HD Map Data Access)

These credentials are required for:

  • Downloading HERE tiles
  • Accessing HERE HD map data
  • Processing HERE HDLM content

Credential Set

{
    "HERE_USER_ID": "...",
    "HERE_CLIENT_ID": "...",
    "HERE_ACCESS_KEY_ID": "...",
    "HERE_ACCESS_KEY_SECRET": "..."
}

These credentials are collectively referred to as HERE Maps API credentials.

14.2.2 HERE Routing API Credentials

These credentials are required for:

  • Route-based map generation
  • Path discovery using HERE Routing APIs

Credential Set

{
    "HERE_ROUTING_API_KEY": "..."
}

This credential is referred to as the HERE Routing API credential.

14.2.3 Configuring Credentials

Credentials must be configured before invoking any HERE2ODR conversion API.

Result ConfigureHereCredentials(
    HereMapsCredentials mapsCredentials,
    HereRoutingCredentials routingCredentials
);

Credential configuration is:

  • Explicit
  • Application-controlled
  • Not persisted by default
  • Required once per session

Credentials may be sourced from:

  • Secure configuration files
  • Environment variables
  • Secret management systems
  • Runtime injection

14.3 Asynchronous Execution Model

All HERE2ODR conversion methods are asynchronous and return a JobHandle<XodrResult>.

Each job:

  • Executes independently
  • Reports progress
  • Supports cancellation
  • Produces structured results or structured errors

Blocking (synchronous) conversion APIs are intentionally not provided.


14.4 Conversion by Geographic Area

ConvertByBoundingBoxAsync

Downloads and converts all HERE tiles intersecting a geographic bounding box.

JobHandle<XodrResult> ConvertByBoundingBoxAsync(
    GeoBoundingBox boundingBox,
    Here2OdrOptions options
);

ConvertByPolygonAsync

Downloads and converts all HERE tiles intersecting a GeoJSON polygon.

JobHandle<XodrResult> ConvertByPolygonAsync(
    GeoJsonPolygon polygon,
    Here2OdrOptions options
);

Required Credentials: HERE Maps API credentials


14.5 Conversion by HERE Tile Identifiers

ConvertByTileIdsAsync

Downloads and converts HERE tiles using explicit tile identifiers.

JobHandle<XodrResult> ConvertByTileIdsAsync(
    IReadOnlyList<string> tileIds,
    Here2OdrOptions options
);

Required Credentials: HERE Maps API credentials


14.6 Conversion from Offline or Encoded HDLM Data

ConvertFromEncodedHdlmAsync

Processes pre-encoded HERE HDLM data without performing network downloads.

JobHandle<XodrResult> ConvertFromEncodedHdlmAsync(
    IReadOnlyList<EncodedHdlmData> hdlmData,
    Here2OdrOptions options
);

Required Credentials: None (offline workflow)


14.7 Route-Based Conversion Using HERE Routing API

This workflow generates a route using HERE Routing APIs and converts only the roads required to represent that route.

ConvertByRouteAsync

JobHandle<XodrResult> ConvertByRouteAsync(
    GeoCoordinate start,
    GeoCoordinate end,
    RoutingOptions routingOptions,
    Here2OdrOptions options
);

Required Credentials: HERE Maps API credentials, HERE Routing API credentials


14.8 Path-Matching Conversion (Selective Road Extraction)

This workflow converts only the roads that match a given path.

ConvertByPathAsync

JobHandle<XodrResult> ConvertByPathAsync(
    PathDefinition path,
    PathMatchingOptions matchingOptions,
    Here2OdrOptions options
);

Supported Path Inputs:

  • HERE Routing API response
  • LineString coordinate sequences
  • GPS trajectory-derived paths

Required Credentials: HERE Maps API credentials; HERE Routing API credentials (if route generation is involved)


14.9 JobHandle Usage for HERE2ODR

All HERE2ODR jobs expose a common job interface.

Checking Job Status

JobStatus GetStatus();
Possible states: - Pending - Running - Completed - Failed - Cancelled

Progress Reporting

double GetProgress();
Progress reflects: - Tile discovery and download - Data decoding - Geometry conversion - OpenDRIVE generation

Awaiting Completion

var result = await here2odrApi
    .ConvertByPolygonAsync(polygon, options)
    .AwaitCompletionAsync();

Retrieving Results

Result<XodrResult> GetResult();
Results may include: - In-memory OpenDRIVE map - Serialized XODR output - Conversion metadata - Warnings and non-fatal issues

Cancelling a Conversion

Result Cancel();
Cancellation is cooperative and stops further downloads and processing.


14.10 Error Handling and Failure Modes

HERE2ODR operations may fail due to:

  • Missing or invalid credentials
  • Network connectivity issues
  • Routing API failures
  • Missing or unsupported HERE data
  • Conversion rule violations

All failures are reported through structured error responses.


14.11 Determinism and Reproducibility

HERE2ODR guarantees:

  • Deterministic output for identical inputs
  • Stable tile selection
  • Repeatable geometry generation
  • Consistent OpenDRIVE serialization

This makes the module suitable for automated pipelines and regression testing.


Summary

The HERE2ODR APIs provide a flexible and robust solution for converting HERE HD map data into OpenDRIVE format. By separating credential responsibilities, enforcing asynchronous execution, and supporting multiple input modes, the module integrates cleanly into both interactive tools and enterprise-scale automation workflows.

15. XODR Explorer APIs

The XODR Explorer APIs provide deep inspection, analysis, querying, and controlled modification capabilities for OpenDRIVE (XODR) maps. This module is designed for analysis-heavy workflows, debugging, auditing, validation support, and advanced tooling where users need to understand and reason about the internal structure and relationships of a map.

The Explorer can operate on:

  • In-memory maps
  • Loaded XODR files
  • Results produced by HERE2ODR or other conversion pipelines

All Explorer APIs are query-first by design, with optional controlled mutation where explicitly allowed.


15.1 Overview

The XODR Explorer enables applications to:

  • Traverse road, lane, and junction graphs
  • Query structural and geometric properties
  • Perform attribute-based and geometry-based filtering
  • Analyze connectivity and reachability
  • Compute statistics and summaries
  • Inspect relationships between entities
  • Perform controlled modifications and re-serialization

This module is especially useful for:

  • Debugging complex maps
  • Automated map analysis
  • QA and auditing pipelines
  • Advanced visualization and reporting tools

15.2 Public Types

struct ExplorerContext { }

struct RoadInfo { }
struct LaneInfo { }
struct JunctionInfo { }

struct ConnectivityGraph { }
struct BoundingBox { }

enum ComparisonOperator
{
    LessThan,
    GreaterThan,
    Equal,
    NotEqual,
    LessOrEqual,
    GreaterOrEqual
}

15.3 Explorer Context APIs

The Explorer operates within an explicit context.

CreateExplorerContext

Result<ExplorerContext> CreateExplorerContext(
    MapHandle map
);
- The context is read-only by default. - Provides a stable snapshot of the map. - Can optionally enable controlled mutation.

DisposeExplorerContext

Result DisposeExplorerContext(
    ExplorerContext context
);


15.4 High-Level Map Queries

GetMapSummary

Returns a high-level summary of the map.

Result<MapSummary> GetMapSummary(
    ExplorerContext context
);

Summary includes: - Number of roads - Number of lane sections - Number of lanes - Number of junctions - Number of objects - Number of signals - Total road length - Map bounding box

GetMapBoundingBox

Result<BoundingBox> GetMapBoundingBox(
    ExplorerContext context
);

GetAllRoads

Result<IReadOnlyList<RoadHandle>> GetAllRoads(
    ExplorerContext context
);


15.5 Road-Level Queries and Filters

GetRoadInfo

Result<RoadInfo> GetRoadInfo(
    ExplorerContext context,
    RoadHandle road
);

FilterRoadsByLength

Result<IReadOnlyList<RoadHandle>> FilterRoadsByLength(
    ExplorerContext context,
    ComparisonOperator op,
    double length
);

FilterRoadsByLaneCount

Result<IReadOnlyList<RoadHandle>> FilterRoadsByLaneCount(
    ExplorerContext context,
    ComparisonOperator op,
    int laneCount
);

FilterRoadsByBoundingBox

Result<IReadOnlyList<RoadHandle>> FilterRoadsByBoundingBox(
    ExplorerContext context,
    BoundingBox box
);

FilterRoadsByLaneWidth

Returns roads having at least one lane matching width criteria.

Result<IReadOnlyList<RoadHandle>> FilterRoadsByLaneWidth(
    ExplorerContext context,
    ComparisonOperator op,
    double widthMeters
);

Example: - Roads having lanes smaller than 5m - Roads having lanes wider than 3.75m


15.6 Lane-Level Queries and Filters

GetLaneInfo

Result<LaneInfo> GetLaneInfo(
    ExplorerContext context,
    LaneHandle lane
);

FilterLanesByType

Result<IReadOnlyList<LaneHandle>> FilterLanesByType(
    ExplorerContext context,
    LaneType type
);

FilterLanesByWidth

Result<IReadOnlyList<LaneHandle>> FilterLanesByWidth(
    ExplorerContext context,
    ComparisonOperator op,
    double widthMeters
);

FilterLanesByHeight

Result<IReadOnlyList<LaneHandle>> FilterLanesByHeight(
    ExplorerContext context,
    ComparisonOperator op,
    double heightMeters
);

FindDisconnectedLanes

Result<IReadOnlyList<LaneHandle>> FindDisconnectedLanes(
    ExplorerContext context
);


15.7 Junction and Connectivity Analysis

GetJunctionInfo

Result<JunctionInfo> GetJunctionInfo(
    ExplorerContext context,
    JunctionHandle junction
);

GetRoadConnectivityGraph

Result<ConnectivityGraph> GetRoadConnectivityGraph(
    ExplorerContext context
);

GetLaneConnectivityGraph

Result<ConnectivityGraph> GetLaneConnectivityGraph(
    ExplorerContext context
);

FindUnreachableRoads

Result<IReadOnlyList<RoadHandle>> FindUnreachableRoads(
    ExplorerContext context
);

FindDeadEndLanes

Result<IReadOnlyList<LaneHandle>> FindDeadEndLanes(
    ExplorerContext context
);

TraceLanePath

Traces reachable lanes from a starting lane.

Result<IReadOnlyList<LaneHandle>> TraceLanePath(
    ExplorerContext context,
    LaneHandle startLane,
    int maxDepth
);

15.8 Object and Signal Analysis

CountObjectsByType

Result<int> CountObjectsByType(
    ExplorerContext context,
    ObjectType type
);

GetObjectsInBoundingBox

Result<IReadOnlyList<ObjectHandle>> GetObjectsInBoundingBox(
    ExplorerContext context,
    BoundingBox box
);

GetSignalsByController

Result<IReadOnlyList<SignalHandle>> GetSignalsByController(
    ExplorerContext context,
    ControllerHandle controller
);

FindSignalsWithoutController

Result<IReadOnlyList<SignalHandle>> FindSignalsWithoutController(
    ExplorerContext context
);


15.9 Statistical and Analytical Queries

ComputeLaneWidthStatistics

Result<LaneWidthStatistics> ComputeLaneWidthStatistics(
    ExplorerContext context
);
Includes: - Min / max / average width - Standard deviation - Distribution buckets

ComputeRoadLengthStatistics

Result<RoadLengthStatistics> ComputeRoadLengthStatistics(
    ExplorerContext context
);

CountEntities

Result<EntityCounts> CountEntities(
    ExplorerContext context
);
Returns counts of: - Roads - Lane sections - Lanes - Junctions - Objects - Signals - Controllers


15.10 Controlled Modification APIs

Explorer supports controlled, explicit modifications for analysis-driven workflows.

EnableModificationMode

Result EnableModificationMode(
    ExplorerContext context
);

RemoveDisconnectedElements

Result RemoveDisconnectedElements(
    ExplorerContext context
);

NormalizeLaneOrdering

Result NormalizeLaneOrdering(
    ExplorerContext context
);

CommitExplorerChanges

Result CommitExplorerChanges(
    ExplorerContext context
);


15.11 Re-Serialization and Export

ExportExplorerView

Exports the current explorer state to XODR.

Result ExportExplorerView(
    ExplorerContext context,
    string outputPath
);

15.12 Usage Example

var ctx = explorerApi.CreateExplorerContext(map).Value;

var narrowRoads = explorerApi.FilterRoadsByLaneWidth(
    ctx,
    ComparisonOperator.LessThan,
    5.0
);

var stats = explorerApi.ComputeLaneWidthStatistics(ctx);

var deadEnds = explorerApi.FindDeadEndLanes(ctx);

Summary

The XODR Explorer APIs transform OpenDRIVE maps from static data files into fully navigable, queryable, and analyzable structures. By supporting rich filtering, connectivity analysis, statistics, and controlled modification, the Explorer enables advanced tooling, auditing, and insight-driven workflows that go far beyond basic map editing.

16. Utilities and Mathematical Helper APIs

The Utilities APIs provide a collection of mathematical, geometric, and normalization utilities that support OpenDRIVE (XODR) authoring, analysis, and correction workflows. These utilities are designed to be reusable across multiple modules and expose functionality that is commonly required when working with road geometry, lanes, and profiles.

This module does not introduce new domain entities (roads, lanes, junctions), but instead operates on existing data to compute, normalize, fit, or reorder information in a deterministic and reproducible manner.


16.1 Overview

The Utilities module enables applications to:

  • Sort lanes correctly from left to right using mathematical rules
  • Normalize lane ordering and lane IDs
  • Fit curves and polynomials to sampled geometry
  • Compute and refit Poly3 and ParamPoly3 representations
  • Perform curvature, heading, and derivative calculations
  • Smooth noisy geometry or profiles
  • Generate derived geometric representations
  • Support cleanup and normalization workflows for imported or converted XODR data

These APIs are especially useful after:

  • Data conversion (e.g., HERE2ODR)
  • Importing externally generated XODR files
  • Manual or automated map editing

And before:

  • Validation or simulation export

16.2 Lane Sorting and Normalization Utilities

Correct lane ordering is critical for OpenDRIVE compliance and downstream simulation usage.

SortLanesLeftToRight
Sorts lanes within a lane section from left to right using geometric evaluation.

Result SortLanesLeftToRight(
    LaneSectionHandle laneSection
);

Behavior

  • Evaluates lane centerlines at a representative s
  • Computes lateral offsets relative to the reference line
  • Orders lanes using signed t coordinates
  • Preserves lane types and attributes

Use Cases

  • Fixing incorrectly ordered lanes
  • Normalizing imported or generated data
  • Preparing maps for validation or export

NormalizeLaneIds
Reassigns lane IDs based on sorted order and OpenDRIVE conventions.

Result NormalizeLaneIds(
    LaneSectionHandle laneSection
);

Behavior

  • Ensures left lanes have positive IDs
  • Right lanes have negative IDs
  • Center lane is 0
  • Preserves connectivity where possible

NormalizeAllLaneSections

Result NormalizeAllLaneSections(
    RoadHandle road
);

16.3 Curve Fitting Utilities

These utilities provide mathematical fitting tools to derive OpenDRIVE-compatible geometry from sampled or noisy data.

FitLineToSamples

Result<LineGeometryParameters> FitLineToSamples(
    IReadOnlyList<XYCoordinate> samples
);

FitArcToSamples
Fits a circular arc to sampled points.

Result<ArcGeometryParameters> FitArcToSamples(
    IReadOnlyList<XYCoordinate> samples
);

FitSpiralToSamples
Fits a clothoid (spiral) to sampled geometry.

Result<SpiralGeometryParameters> FitSpiralToSamples(
    IReadOnlyList<XYCoordinate> samples
);


16.4 Poly3 and ParamPoly3 Utilities

Poly3 and ParamPoly3 curves are commonly used to represent road geometry and profiles in OpenDRIVE.

FitPoly3
Fits a cubic polynomial to sampled data.

Result<Poly3Parameters> FitPoly3(
    IReadOnlyList<double> sSamples,
    IReadOnlyList<double> values
);

Use Cases

  • Elevation profile fitting
  • Lane width fitting
  • Superelevation fitting
  • Lateral shape fitting

FitParamPoly3
Fits a parametric cubic curve to sampled XY geometry.

Result<ParamPoly3Parameters> FitParamPoly3(
    IReadOnlyList<XYCoordinate> samples
);

RefitGeometryAsPoly3

Result RefitGeometryAsPoly3(
    GeometryHandle geometry,
    int sampleCount
);


16.5 Derivative and Curvature Calculations

These utilities expose low-level mathematical evaluations commonly required in analysis and validation.

ComputeHeading

Result<double> ComputeHeading(
    IReadOnlyList<XYCoordinate> samples,
    int index
);

ComputeCurvature

Result<double> ComputeCurvature(
    IReadOnlyList<XYCoordinate> samples,
    int index
);

ComputeCurvatureProfile

Result<IReadOnlyList<double>> ComputeCurvatureProfile(
    IReadOnlyList<XYCoordinate> samples
);


16.6 Geometry Smoothing and Cleanup

These utilities help clean noisy or overly complex data.

SmoothPolyline

Result<IReadOnlyList<XYCoordinate>> SmoothPolyline(
    IReadOnlyList<XYCoordinate> samples,
    SmoothingOptions options
);

SimplifyPolyline
Reduces point count while preserving shape.

Result<IReadOnlyList<XYCoordinate>> SimplifyPolyline(
    IReadOnlyList<XYCoordinate> samples,
    double tolerance
);

RemoveShortGeometrySegments

Result RemoveShortGeometrySegments(
    RoadHandle road,
    double minLength
);


16.7 Sampling and Resampling Utilities

ResampleGeometry

Result<IReadOnlyList<XYCoordinate>> ResampleGeometry(
    GeometryHandle geometry,
    double stepSize
);

ResampleLaneCenterline

Result<IReadOnlyList<XYCoordinate>> ResampleLaneCenterline(
    LaneHandle lane,
    double stepSize
);


16.8 Consistency and Normalization Utilities

NormalizeRoadDirection

Result NormalizeRoadDirection(
    RoadHandle road
);

NormalizeJunctionLaneLinks

Result NormalizeJunctionLaneLinks(
    JunctionHandle junction
);

CleanupUnusedElements

Result CleanupUnusedElements(
    MapHandle map
);

Removes:

  • Unreferenced lanes
  • Empty lane sections
  • Orphaned objects
  • Unused controllers

16.9 Usage Example

utilitiesApi.SortLanesLeftToRight(laneSection);
utilitiesApi.NormalizeLaneIds(laneSection);

var poly3 = utilitiesApi.FitPoly3(sSamples, elevationSamples).Value;

utilitiesApi.RemoveShortGeometrySegments(road, minLength: 1.0);

Summary

The Utilities APIs provide the mathematical backbone required for reliable OpenDRIVE authoring and processing. By exposing lane sorting, curve fitting, polynomial evaluation, smoothing, and normalization utilities, the Replimap SDK enables applications to build clean, compliant, and simulation-ready maps from a wide variety of data sources.

17. Asynchronous Operations

The Replimap SDK provides a unified and consistent asynchronous execution model for operations that may require significant processing time, external I/O, or large data traversal. This includes workflows such as validation, data conversion, deep analysis, and batch processing.

This section describes the asynchronous programming model, lifecycle of asynchronous jobs, and recommended usage patterns.


17.1 When to Use Asynchronous APIs

Asynchronous APIs are used when an operation:

  • May take a noticeable amount of time to complete
  • Performs network I/O (e.g., HERE data download)
  • Processes large or complex maps
  • Performs full-map analysis or validation
  • Should not block the calling thread

Typical asynchronous modules include:

  • HERE2ODR
  • XODR Validator (full-map validation)
  • XODR Explorer (deep analysis)
  • Utility batch operations

17.2 JobHandle Concept

All asynchronous operations return a JobHandle<T>, which represents a running or scheduled background task.

A job handle:

  • Is created immediately
  • Executes independently
  • Represents exactly one operation
  • Produces a typed result upon completion

The job handle is the primary interface for monitoring, controlling, and retrieving results from asynchronous operations.


17.3 Job Lifecycle and States

Each job progresses through a well-defined lifecycle.

Job States:

  • Pending – Job created but not yet started
  • Running – Job currently executing
  • Completed – Job finished successfully
  • Failed – Job terminated due to an error
  • Cancelled – Job was explicitly cancelled

State transitions are deterministic and monotonic.


17.4 Querying Job Status

GetStatus

JobStatus GetStatus();
This method returns the current state of the job and is safe to call repeatedly.


17.5 Progress Reporting

GetProgress

double GetProgress();
- Returns a value in the range [0.0, 1.0] - Progress values are monotonic - Granularity depends on the operation type - Not all operations report fine-grained progress

Progress reporting is designed for UI feedback and monitoring dashboards.


17.6 Retrieving Results

Results are available once the job reaches the Completed state.

GetResult

Result<T> GetResult();
Calling GetResult():

  • Is valid only after completion
  • Returns the operation result or an error
  • Does not block

17.7 Awaiting Completion (Async/Await Integration)

For applications using modern .NET async workflows, job handles provide awaitable completion helpers.

AwaitCompletionAsync

var result = await job.AwaitCompletionAsync();
This pattern:

  • Does not block threads
  • Integrates with async / await
  • Throws no raw exceptions
  • Returns structured results

This is the recommended approach for most applications.


17.8 Cancellation

Jobs can be cancelled explicitly.

Cancel

Result Cancel();
Cancellation behavior:

  • Is cooperative
  • Stops further processing where possible
  • May not interrupt non-interruptible operations
  • Results in the Cancelled state

Cancelled jobs do not produce partial results.


17.9 Error Handling in Asynchronous Operations

If a job fails:

  • The job state becomes Failed
  • The error is available via GetResult()
  • No exceptions are thrown implicitly

Errors include:

  • Execution failures
  • External service failures
  • Invalid input or configuration
  • Resource limitations

Applications must explicitly inspect job results.


17.10 Threading and Concurrency Considerations

  • Asynchronous jobs run on SDK-managed execution contexts
  • Jobs do not block the calling thread
  • Concurrent jobs may execute in parallel
  • Access to shared map state must be coordinated by the caller
  • Modifying a map while an asynchronous job is operating on it is not supported unless explicitly documented

Interactive Applications

  • Use async APIs for long-running operations
  • Display progress to users
  • Allow cancellation
  • Avoid blocking UI threads

Batch and Automation

  • Schedule multiple jobs
  • Poll or await completion
  • Log structured results
  • Fail pipelines on error states

CI/CD Pipelines

  • Use black-box async validation
  • Store validation reports
  • Compare results across builds

17.12 Anti-Patterns to Avoid

  • Blocking on async jobs using busy-wait loops
  • Ignoring job results
  • Assuming completion without checking status
  • Modifying shared map state during execution

Summary

The Replimap SDK’s asynchronous execution model provides a robust, predictable, and scalable foundation for handling long-running operations. By exposing a consistent JobHandle abstraction with progress reporting, cancellation, and structured results, the SDK enables safe integration into interactive tools, backend services, and automated pipelines alike.

18. Error Handling and Diagnostics

The Replimap SDK is designed with a robust, explicit, and predictable error handling model. All public APIs follow a result-based pattern, ensuring that failures are reported in a structured and recoverable manner without causing unexpected crashes or unhandled exceptions.

This section explains how errors are represented, categorized, reported, and diagnosed across the SDK.


18.1 Design Principles

The error handling system follows these core principles:

  • No implicit crashes: Public APIs do not throw raw exceptions under normal operation
  • Explicit error reporting: All failures are returned as structured results
  • Recoverability by default: Most errors allow applications to continue execution
  • Deterministic behavior: Identical failures produce identical error outputs
  • Actionable diagnostics: Errors include context to aid debugging and resolution

18.2 Result-Based API Pattern

All SDK APIs return a Result or Result<T> type.

Result

A result contains:

  • Success or failure state
  • A return value (on success)
  • An error object (on failure)

Applications are expected to explicitly check results.

var result = roadApi.CreateRoad(map, "R1", RoadRule.RightHandTraffic);

if (!result.IsSuccess)
{
    Log(result.Error);
    return;
}

18.3 Public Error Types

This section defines the public error-related types used throughout the Replimap SDK.

All error information returned by SDK APIs conforms to this model.


Error

Represents a structured description of a failed operation.

struct Error
{
    ErrorCode ErrorCode;
    ErrorCategory Category;
    ErrorSeverity Severity;
    string Message;

    // Optional diagnostic information
    string Context;
    string Location;
    object Details;
}

Description - Returned via Result.Error when an operation fails - Never thrown as an exception under normal operation - Designed to be machine-readable and human-readable


ErrorCode

Identifies the specific failure condition.

enum ErrorCode
{
    // Defined error codes are documented in Section 17.12
}

Notes - Error codes are stable across SDK versions - Used for programmatic branching and recovery - A complete list is provided in Section 17.12 – Common Error Codes Reference


ErrorCategory

Classifies the error by subsystem or responsibility.

enum ErrorCategory
{
    Validation,
    Geometry,
    Topology,
    IO,
    Conversion,
    Internal
}

Usage - High-level grouping - Useful for logging, filtering, and diagnostics - Not intended for fine-grained control flow


ErrorSeverity

Indicates the seriousness of the error.

enum ErrorSeverity
{
    Info,
    Warning,
    Error,
    Critical
}

Semantics - Info – Informational, no action required - Warning – Non-fatal issue, operation may still succeed - Error – Operation failed - Critical – Unrecoverable failure, session may be invalid


Result and Result<T> (Reference)

All SDK APIs return either Result or Result<T>:

struct Result
{
    bool IsSuccess;
    Error Error;
}

struct Result<T>
{
    bool IsSuccess;
    T Value;
    Error Error;
}

Rules - Value is valid only when IsSuccess == true - Error is non-null only when IsSuccess == false - Applications must always check IsSuccess

Notes - Errors are explicit, never implicit - APIs do not rely on exceptions for control flow - This model applies consistently across: - Core APIs - Geometry APIs - Conversion APIs - Asynchronous operations


18.4 Error Object Structure

An error object contains structured diagnostic information.

Typical fields include:

  • ErrorCode – Stable, machine-readable identifier
  • Category – Broad error classification
  • Message – Human-readable description
  • Severity – Informational, warning, error, fatal
  • Context – Related entity identifiers (road ID, lane ID, junction ID, etc.)
  • Location – Optional spatial or s-range information
  • Details – Optional extended diagnostic data

This structure allows both humans and automated systems to interpret errors reliably.


18.5 Error Categories

Errors are grouped into well-defined categories to guide handling strategies.

Input and Configuration Errors

  • Invalid parameters
  • Missing required values
  • Invalid credential configuration
  • Unsupported options

Structural Errors

  • Broken OpenDRIVE structure
  • Missing references
  • Invalid connectivity
  • Duplicate identifiers

Geometry Errors

  • Discontinuous geometry
  • Invalid curvature or polynomial coefficients
  • Degenerate or zero-length segments

Topology Errors

  • Lane predecessor/successor mismatches
  • Invalid junction connectivity
  • Unreachable roads or lanes

External Dependency Errors

  • HERE API authentication failures
  • Network errors
  • Routing API failures
  • Missing external data

Execution Errors

  • Resource exhaustion
  • Operation cancellation
  • Internal processing failures

18.6 Severity Levels

Each error includes a severity level that indicates its impact.

  • Info – Informational messages, no action required
  • Warning – Non-critical issues that may affect quality
  • Error – Operation failed, but application may continue
  • Fatal – Unrecoverable error, operation cannot proceed

Severity levels are especially important in validation and analysis workflows.


18.7 Recoverable vs Fatal Errors

Most SDK errors are recoverable, allowing applications to:

  • Adjust inputs
  • Retry operations
  • Skip problematic elements
  • Continue processing unaffected data

Fatal errors are rare and explicitly documented. They typically indicate:

  • Corrupted internal state
  • Unsupported runtime environment
  • Incompatible SDK usage

18.8 Error Handling in Asynchronous Operations

Asynchronous jobs report errors through their job results.

  • Failed jobs transition to the Failed state
  • Errors are retrieved via GetResult()
  • No exceptions are thrown implicitly
if (job.GetStatus() == JobStatus.Failed)
{
    var error = job.GetResult().Error;
    Log(error);
}

Cancelled jobs report a distinct cancellation state.


18.9 Diagnostics and Logging

The SDK provides hooks for diagnostics and logging to support debugging and production monitoring.

Typical diagnostic features include:

  • Structured log events
  • Operation lifecycle logging
  • External service call tracing
  • Validation and conversion summaries

Logging integration is designed to work with:

  • Application-level logging frameworks
  • File-based logging
  • Centralized monitoring systems

18.10 Debugging and Inspection Support

To assist debugging and analysis, the SDK exposes:

  • Detailed validation reports
  • Explorer-based inspection APIs
  • Connectivity and graph visualization data
  • Map and entity summaries
  • Deterministic reproduction of errors

These tools allow developers to investigate issues without modifying or corrupting map data.


Interactive Applications

  • Display warnings without blocking workflows
  • Block operations only on fatal or critical errors
  • Provide actionable feedback to users

Automation and CI Pipelines

  • Treat errors as failures
  • Persist error reports
  • Fail builds on critical validation issues

Long-Running Services

  • Log structured errors
  • Retry transient failures
  • Monitor error frequency and trends

18.12 Anti-Patterns to Avoid

  • Ignoring result checks
  • Relying on exceptions for control flow
  • Swallowing errors without logging
  • Assuming success without validation
  • Retrying unrecoverable errors indefinitely

18.13 Common Error Codes Reference

This section lists commonly returned error codes across the SDK.

Each error code is stable and may be returned by multiple APIs.

DuplicateRoadId

A road with the specified identifier already exists in the map.

InvalidRoadRule

The specified road rule is invalid, unsupported, or incompatible with the current map configuration.

InvalidRoadHandle

The provided road handle is invalid, expired, or does not belong to the current map.

InvalidGeometryParameters

One or more geometry parameters are invalid, undefined, or mathematically inconsistent.

GeometryContinuityViolation

The provided geometry breaks continuity with adjacent geometry segments.

InvalidObjectType

The specified object type is unsupported or not valid in the given context.

InvalidPosition

The specified spatial position (s, t, z) is outside valid bounds or inconsistent with the road geometry.

DuplicateJunctionId

A junction with the specified identifier already exists in the map.

InvalidJunctionType

The specified junction type is invalid or not supported by the SDK.

LaneNotRemovable

Only the outer-most lane can be removed from any given road. Attempting to delete a center or inner lane is not permitted and results in this error.

InvalidLaneMarkingDefinition

The lane marking definition is invalid or incomplete.

LaneMarkingOverlap

The lane marking overlaps with an existing marking on the same side.

LaneMarkingNotFound

The specified lane marking does not exist.

InvalidLaneMarkingSide

The specified lane marking side is not valid in this context.

NoEffectiveLaneMarking

No lane-level or road-level lane marking exists at the specified position.

RoadDefaultLaneMarkingNotFound

The specified road-level default lane marking does not exist.

UnsupportedLaneMarkingForLaneType

The lane marking type is not supported for the given lane type.

InvalidLaneMarkingForLaneSide

The lane marking is not valid for the specified lane side.


Notes

  • Error codes may appear in multiple modules.
  • Additional error codes may be introduced in future SDK versions.
  • Detailed handling guidance is provided in the surrounding sections of this chapter.

Summary

The Replimap SDK’s error handling and diagnostics system provides a clear, consistent, and robust framework for detecting, reporting, and resolving issues. By enforcing explicit result-based APIs, structured error reporting, and strong diagnostic support, the SDK enables safe integration into interactive tools, automated pipelines, and enterprise-scale systems.

19. Performance and Best Practices

This section provides guidance on using the Replimap SDK efficiently and safely in performance-sensitive environments. The recommendations apply to interactive desktop tools, headless batch pipelines, CI systems, and long-running backend services.

The SDK is designed to scale to large and complex OpenDRIVE maps, but optimal performance depends on how the APIs are used.


19.1 General Performance Principles

The following principles apply across all modules:

  • Prefer explicit control over implicit behavior
  • Minimize repeated full-map traversals
  • Use queries for inspection, commands for modification
  • Batch related operations where possible
  • Avoid unnecessary geometry recalculation
  • Use asynchronous APIs for long-running tasks

19.2 Session and Map Management

Best Practices

  • Reuse a session for related workflows
  • Avoid creating excessive short-lived sessions
  • Dispose sessions explicitly when finished
  • Keep map lifetimes well-defined

Avoid

  • Creating a new session for every small operation
  • Holding sessions open indefinitely without purpose
  • Mixing unrelated workflows in the same session without isolation

19.3 Command Batching and Edit Strategy

Many SDK operations trigger internal consistency updates.

Recommended Patterns

  • Group related commands together
  • Perform bulk edits before validation
  • Apply normalization and cleanup at logical checkpoints
  • Prefer single-pass modifications over repeated micro-edits

Example

  1. Create roads and lanes first
  2. Then assign widths, offsets, and connectivity
  3. Then normalize and validate

19.4 Geometry Performance Considerations

Geometry operations can be computationally expensive.

Recommendations

  • Avoid excessive geometry sampling at very fine resolutions
  • Cache sampled results when used repeatedly
  • Use resampling utilities with appropriate step sizes
  • Avoid frequent refitting of curves unless necessary

Curve Fitting

  • Use curve fitting utilities after data ingestion, not during every edit
  • Prefer Poly3/ParamPoly3 fitting only when required by the target workflow

19.5 Lane and Topology Operations

Lane and connectivity updates may affect large portions of the map.

Best Practices

  • Modify lane topology before attaching objects or signals
  • Normalize lane ordering after bulk changes
  • Validate connectivity incrementally, not after every edit

Avoid

  • Rebuilding connectivity graphs repeatedly
  • Modifying lane IDs after connectivity is finalized

19.6 Validation Performance

Validation can range from lightweight to computationally intensive.

Recommendations

  • Use partial validation during interactive editing
  • Use full-map validation only when required
  • Prefer asynchronous validation for large maps
  • Store validation reports instead of re-running identical checks

CI / Automation

  • Use black-box validation for reproducibility
  • Fail fast on fatal or critical errors

19.7 HERE2ODR Performance Guidelines

HERE2ODR workflows involve external services and large datasets.

Best Practices

  • Limit geographic scope where possible
  • Use tile-based or route-based conversion for targeted maps
  • Cache HERE tiles when allowed
  • Avoid repeated conversions of identical inputs

Async Usage

  • Always use async conversion APIs
  • Monitor progress instead of blocking
  • Support cancellation for user-triggered workflows

19.8 Explorer and Analysis Performance

Explorer queries may traverse large graphs.

Recommendations

  • Use filters to narrow search scope
  • Avoid repeated full-map queries in loops
  • Compute statistics once and reuse results
  • Use bounding boxes to limit spatial queries

19.9 Memory Management

Large maps can consume significant memory.

Best Practices

  • Dispose maps and sessions explicitly
  • Avoid keeping multiple full-map copies in memory
  • Use cloning selectively
  • Prefer black-box analysis for external XODR files

19.10 Asynchronous Concurrency Guidelines

  • Limit the number of concurrent jobs
  • Avoid running multiple heavy jobs on the same map
  • Coordinate access to shared map state
  • Use job completion callbacks or await patterns

19.11 Common Anti-Patterns

Avoid the following patterns:

  • Running validation after every single edit
  • Blocking on async jobs using busy-wait loops
  • Ignoring result objects and error states
  • Recomputing geometry unnecessarily
  • Mixing analysis and modification in the same workflow
  • Treating the SDK as a UI-driven system

Interactive Editing

  • Fine-grained edits
  • Partial validation
  • Deferred normalization
  • Responsive async operations

Batch Processing

  • Deterministic inputs
  • Async conversion and validation
  • Structured logging
  • Repeatable outputs

Enterprise Integration

  • Centralized error handling
  • Performance monitoring
  • Version-controlled outputs
  • Clear lifecycle management

Summary

By following these performance and best-practice guidelines, applications can integrate the Replimap SDK efficiently and reliably across a wide range of use cases. Proper session management, thoughtful command batching, careful use of geometry operations, and disciplined asynchronous workflows ensure scalability, stability, and predictable behavior in production environments.

20. Examples and Typical Workflows

This section presents complete, real-world workflows demonstrating how the Replimap SDK can be used to create, convert, analyze, validate, and export OpenDRIVE (XODR) maps. The examples are written in C# and reflect recommended usage patterns for interactive tools, batch processing, and automated pipelines.


20.1 Creating a Map from Scratch

This workflow demonstrates how to create a new OpenDRIVE map programmatically.

using var session = ReplimapSession.Create();

var mapResult = session.CreateMap();
if (!mapResult.IsSuccess)
    throw new Exception(mapResult.Error.Message);

var map = mapResult.Value;

20.2 Creating Roads and Defining Geometry

var road = roadApi.CreateRoad(
    roadId: "R_Main",
    rule: RoadRule.RightHandTraffic
).Value;

// Add plan-view geometry
geometryApi.AddGeometrySegment(
    road,
    GeometryType.Line,
    new LineGeometryParameters { Length = 100.0 }
);

geometryApi.AddGeometrySegment(
    road,
    GeometryType.Arc,
    new ArcGeometryParameters
    {
        Length = 50.0,
        Curvature = 0.01
    }
);

20.3 Adding Elevation, Superelevation, and Lateral Shape

geometryApi.AddElevationSegment(
    road,
    sStart: 0.0,
    new ElevationPolynomial
    {
        A = 0.0,
        B = 0.02,
        C = 0.0,
        D = 0.0
    }
);

geometryApi.AddSuperelevationSegment(
    road,
    sStart: 0.0,
    new SuperelevationPolynomial
    {
        A = 0.0,
        B = 0.001,
        C = 0.0,
        D = 0.0
    }
);

20.4 Creating Lane Sections and Lanes

var laneSection = roadApi.AddLaneSection(
    road,
    sStart: 0.0
).Value;

// Right driving lane
var rightLane = roadApi.AddLane(
    laneSection,
    LaneSide.Right,
    laneId: -1,
    LaneType.Driving
).Value;

// Left driving lane
var leftLane = roadApi.AddLane(
    laneSection,
    LaneSide.Left,
    laneId: 1,
    LaneType.Driving
).Value;

// Set lane widths
roadApi.AddLaneWidthSegment(
    rightLane,
    sOffset: 0.0,
    new WidthPolynomial { A = 3.5 }
);

roadApi.AddLaneWidthSegment(
    leftLane,
    sOffset: 0.0,
    new WidthPolynomial { A = 3.5 }
);

20.5 Sorting and Normalizing Lanes (Utilities)

utilitiesApi.SortLanesLeftToRight(laneSection);
utilitiesApi.NormalizeLaneIds(laneSection);
This step is strongly recommended after bulk lane creation or import.


20.6 Creating a Junction Between Roads

var roadB = roadApi.CreateRoad(
    "R_Cross",
    RoadRule.RightHandTraffic
).Value;

// Add minimal geometry for second road
geometryApi.AddGeometrySegment(
    roadB,
    GeometryType.Line,
    new LineGeometryParameters { Length = 60.0 }
);

var junction = junctionApi.CreateJunction(
    "J_Intersection",
    JunctionType.Default
).Value;

junctionApi.AddRoadToJunction(
    junction,
    road,
    ContactPoint.End
);

junctionApi.AddRoadToJunction(
    junction,
    roadB,
    ContactPoint.Start
);

// Auto-generate lane-to-lane connectivity
junctionApi.AutoGenerateJunctionConnections(junction);

20.7 Adding Roadside Objects and Signals

// Add a guardrail
var guardrail = objectApi.AddObject(
    road,
    ObjectType.GuardRail,
    s: 5.0,
    t: -2.5
).Value;

// Repeat guardrail every 5 meters
objectApi.SetObjectRepeat(
    guardrail,
    sStart: 5.0,
    sEnd: 95.0,
    distance: 5.0
);

// Add traffic signal
var signal = signalApi.AddSignal(
    road,
    s: 40.0,
    t: -1.5,
    SignalType.Dynamic
).Value;

// Create controller
var controller = controllerApi.CreateController("CTRL_1").Value;
controllerApi.AssignSignalToController(controller, signal);

20.8 Using Mathematical Utilities (Curve Fitting)

var samples = geometryApi.ResampleGeometry(
    geometryHandle,
    stepSize: 1.0
).Value;

// Fit Poly3 to elevation samples
var poly3 = utilitiesApi.FitPoly3(
    sSamples,
    elevationSamples
).Value;

20.9 HERE2ODR Conversion — Bounding Box

here2odrApi.ConfigureHereCredentials(
    mapsCredentials,
    routingCredentials
);

var job = here2odrApi.ConvertByBoundingBoxAsync(
    new GeoBoundingBox
    {
        MinLat = 52.51,
        MinLon = 13.38,
        MaxLat = 52.53,
        MaxLon = 13.42
    },
    new Here2OdrOptions()
);

// Await completion
var conversionResult = await job.AwaitCompletionAsync();
var convertedMap = conversionResult.Value.Map;

20.10 HERE2ODR Conversion — Route-Based

var routeJob = here2odrApi.ConvertByRouteAsync(
    start: new GeoCoordinate(52.5200, 13.4050),
    end: new GeoCoordinate(52.5150, 13.4550),
    routingOptions: new RoutingOptions(),
    options: new Here2OdrOptions()
);

while (!routeJob.IsCompleted())
{
    Console.WriteLine($"Progress: {routeJob.GetProgress():P}");
    await Task.Delay(500);
}

var routeMap = routeJob.GetResult().Value.Map;

20.11 Deep Analysis Using XODR Explorer

var ctx = explorerApi.CreateExplorerContext(map).Value;

// Find narrow roads
var narrowRoads = explorerApi.FilterRoadsByLaneWidth(
    ctx,
    ComparisonOperator.LessThan,
    3.0
);

// Find disconnected lanes
var deadEnds = explorerApi.FindDeadEndLanes(ctx);

// Compute statistics
var stats = explorerApi.ComputeLaneWidthStatistics(ctx);

20.12 Validation Workflow (Sync + Async)

Quick Synchronous Validation

var report = validatorApi.ValidateMap(map).Value;

foreach (var issue in report.Issues)
{
    Console.WriteLine($"{issue.Severity}: {issue.Message}");
}

Full Black-Box Asynchronous Validation

var validationJob = validatorApi.ValidateXodrFileAsync(
    "input.xodr",
    new ValidationOptions { StrictMode = true }
);

var validationResult = await validationJob.AwaitCompletionAsync();


20.13 Cleanup, Normalization, and Final Validation

utilitiesApi.NormalizeAllLaneSections(road);
utilitiesApi.CleanupUnusedElements(map);

var finalReport = validatorApi.ValidateMap(map).Value;

20.14 Saving and Exporting the Map

session.SaveMap(
    map,
    "final_output.xodr"
);

20.15 Typical End-to-End Pipeline (Summary)

  • Create or load map
  • Add roads, geometry, lanes
  • Normalize and sort lanes
  • Add junctions, objects, signals
  • Apply math utilities and cleanup
  • Validate (partial → full)
  • Export OpenDRIVE

Summary

These workflows demonstrate how the Replimap SDK can be used to build complete OpenDRIVE pipelines—from raw HERE data ingestion to detailed map authoring, analysis, validation, and export. The SDK’s modular design allows these workflows to be composed, automated, and scaled across interactive tools and enterprise environments.

21. Automation and Procedural Operations APIs

Automation and Procedural Operations APIs provide high-level, rule-driven batch operations that act on a map as a whole. These APIs encapsulate multi-step workflows that may modify roads, lanes, junctions, objects, and signals based on user-defined rules and parameters.

Automation APIs are intended to:

  • Reduce repetitive manual editing
  • Apply consistent rules across large maps
  • Enable batch processing and headless workflows
  • Serve as building blocks for editor “tools” and presets

Automation operations are explicit, deterministic, and parameterized. They do not introduce hidden behavior and do not replace low-level editing APIs.

21.1 Design Principles

Automation APIs follow these principles:

  • Operate at map scope
  • Express intent, not implementation details
  • Encapsulate multi-entity modifications
  • Are deterministic given the same inputs and options
  • Use explicit options structures
  • May internally invoke multiple SDK modules
  • Are safe for both interactive and headless usage

Automation APIs are modeled as commands. Inspection of results is performed using existing query APIs.

21.2 Execution Model

Automation operations:

  • Execute synchronously in the current SDK version
  • Return a single Result
  • Apply changes atomically (no partial application on failure)

The execution model is designed to allow future extension to: - Asynchronous execution using JobHandle - Dry-run or preview modes - Profile-based or preset-driven execution

21.3 Lane-Based Automations

Lane-based automations apply rule-driven transformations to lanes that satisfy specific criteria.

Sidewalk Height Automation

Applies a uniform or rule-based height profile to all sidewalk lanes in the map.

Typical use cases include: - Normalizing sidewalk elevation - Preparing maps for pedestrian simulation - Enforcing design or export constraints

Commands

Result ApplySidewalkHeightAutomation(
    MapHandle map,
    SidewalkHeightAutomationOptions options
);
// Applies lane height definitions to all sidewalk lanes
// Only lanes classified as sidewalks are affected

struct SidewalkHeightAutomationOptions
{
    double Height;
    bool OverrideExistingHeights;
}

21.4 Junction-Based Automations

Junction-based automations operate on junctions and their connected roads and lanes.

Stop Line Generation

Automatically adds stop line objects to qualifying junction approaches using catalog-based object definitions.

This automation: - Uses the Object Catalog - Applies placement rules relative to junction geometry - Avoids duplicating existing stop lines unless explicitly requested

Commands

Result AddStopLinesToJunctions(
    MapHandle map,
    StopLineAutomationOptions options
);
// Adds stop line objects to all qualifying junction approaches
// Existing stop lines are preserved unless overridden

struct StopLineAutomationOptions
{
    double OffsetFromJunction;
    bool OverrideExisting;
    string StopLineCatalogId;
}

21.5 Roadside Automations

Roadside automations populate roadside areas with objects based on geometric, semantic, and spacing rules.

Roadside Vegetation Population

Populates roadside vegetation such as trees or shrubs along eligible roads.

This automation: - Uses road geometry and lane layout - Places objects at regular intervals - Can optionally respect green-space constraints

Commands

Result PopulateRoadsideVegetation(
    MapHandle map,
    VegetationAutomationOptions options
);
// Populates roadside vegetation objects along eligible roads
// Objects are placed using spacing and offset rules

struct VegetationAutomationOptions
{
    string TreeCatalogId;
    double Spacing;
    double LateralOffset;
    bool RestrictToGreenSpaces;
    bool AvoidJunctions;
}

21.6 Example Use Cases

Normalize Sidewalk Heights

automationApi.ApplySidewalkHeightAutomation(
    map,
    new SidewalkHeightAutomationOptions
    {
        Height = 0.15,
        OverrideExistingHeights = true
    }
);
Use case:
Prepare an urban map for pedestrian simulation by enforcing consistent sidewalk elevation.


Add Stop Lines to All Junctions

automationApi.AddStopLinesToJunctions(
    map,
    new StopLineAutomationOptions
    {
        OffsetFromJunction = 2.0,
        OverrideExisting = false,
        StopLineCatalogId = "roadmark.stop_line.standard"
    }
);
Use case:
Rapidly make a converted map compliant with basic traffic control expectations.


Populate Roadside Trees

automationApi.PopulateRoadsideVegetation(
    map,
    new VegetationAutomationOptions
    {
        TreeCatalogId = "vegetation.tree.deciduous",
        Spacing = 10.0,
        LateralOffset = 3.5,
        RestrictToGreenSpaces = true,
        AvoidJunctions = true
    }
);
Use case:
Enhance semantic richness and visual realism for simulation or visualization workflows.

21.7 Error Handling

Automation APIs return structured errors in the following cases:

  • Invalid map handle
  • Invalid automation options
  • Missing required catalog entries
  • Conflicting or unsatisfiable rules
  • Map state not suitable for the requested automation

If an automation fails, no partial changes are applied.

21.8 Extensibility

The Automation APIs are designed for future extension, including:

  • Asynchronous execution
  • Dry-run and preview support
  • Profile-based automations (city, highway, country rules)
  • User-defined or plugin-based automations

Summary

Automation and Procedural Operations APIs provide a powerful, scalable mechanism for applying rule-based transformations to maps. By keeping these operations separate from core editing APIs, the SDK enables advanced workflows while preserving clarity, determinism, and long-term maintainability.


22. Versioning, Compatibility, and Support

This section describes how the Replimap SDK and API are versioned, how compatibility is managed across releases, and how clients can expect long-term support and maintenance.

The goal is to ensure predictability, stability, and trust for integrations built on top of the SDK.


22.1 Versioning Strategy

The Replimap SDK follows semantic versioning:

MAJOR.MINOR.PATCH
  • MAJOR – Breaking changes to the public API or data contracts
  • MINOR – Backward-compatible feature additions
  • PATCH – Bug fixes, performance improvements, and internal corrections

Version numbers apply to the SDK as a whole, and all shipped modules share the same version.


22.2 API Stability Guarantees

The SDK provides the following stability guarantees:

  • Public APIs documented in this guide are considered stable
  • Breaking changes occur only in major releases
  • Experimental or preview APIs are explicitly marked
  • Internal APIs are not part of the compatibility contract

Clients are encouraged to depend only on documented public APIs.


22.3 Backward Compatibility

Backward compatibility is maintained within a major version:

  • Existing method signatures remain valid
  • Behavior remains consistent unless explicitly documented
  • New optional parameters may be introduced with safe defaults
  • Validation and conversion behavior changes are documented in release notes

Where backward compatibility cannot be maintained, the change is deferred to a major release.


22.4 Deprecation Policy

APIs are deprecated in a controlled and transparent manner.

Deprecation process:

  1. API is marked as deprecated in documentation
  2. Alternative API is provided where applicable
  3. Deprecated API remains available for at least one major version
  4. Removal occurs only in a future major release

This policy ensures clients have sufficient time to migrate.


22.5 OpenDRIVE Compatibility

The SDK supports multiple versions of ASAM OpenDRIVE.

  • Import and export behavior is version-aware
  • Unsupported or deprecated OpenDRIVE features are reported explicitly
  • Version-specific validation rules are applied where relevant
  • Conversion workflows preserve semantic correctness across versions

Supported OpenDRIVE versions are documented per SDK release.


22.6 External Dependency Compatibility

For modules that rely on external services or formats:

HERE APIs

  • Compatibility is maintained with supported HERE API versions
  • Credential and endpoint changes are documented
  • Breaking changes in HERE services may require SDK updates

Runtime and Platform

  • Supported .NET runtimes are specified per release
  • Platform-specific limitations are documented
  • Unity compatibility is documented separately where applicable

22.7 Upgrade Guidelines

When upgrading the SDK:

  • Review release notes for breaking changes
  • Update SDK assemblies as a complete set
  • Rebuild and run existing validation workflows
  • Address any deprecated API usage
  • Re-run automated tests and validation pipelines

Upgrading within a minor or patch version typically requires no code changes.


22.8 Support and Maintenance

Support options depend on the engagement agreement and may include:

  • Issue tracking and bug reports
  • Documentation clarifications
  • API usage guidance
  • Performance and integration assistance
  • Validation rule extensions

Support requests should include:

  • SDK version
  • Reproduction steps
  • Input data (where possible)
  • Validation or error reports

22.9 Reporting Issues

When reporting issues, provide:

  • Clear description of the problem
  • Relevant API calls or workflows
  • Logs or validation reports
  • OpenDRIVE input or output files (if applicable)

This helps ensure timely and accurate resolution.


22.10 Long-Term Vision

The Replimap SDK is designed as a long-lived backend platform for OpenDRIVE authoring, conversion, validation, and analysis.

Future roadmap goals include:

  • Expanded conversion pipelines
  • Additional validation rule sets
  • Enhanced analysis and exploration capabilities
  • Continued performance improvements
  • Strong backward compatibility guarantees

Client feedback plays a key role in shaping future development.


23. Sample Maps APIs

Sample Maps APIs provide access to a curated set of read-only example XODR maps bundled with the Replimap SDK. These sample maps are intended for learning, testing, prototyping, and validation workflows.

Sample maps:

  • Are shipped with the SDK installation
  • Are accessed using stable sample identifiers
  • Are read-only templates
  • Can be loaded or cloned into editable sessions
  • Do not expose file paths or filesystem details

23.1 Design Principles

Sample Maps APIs follow these principles:

  • Sample content is bundled and versioned with the SDK
  • Access is identifier-based, not path-based
  • Sample maps are immutable
  • Loaded or cloned maps behave like regular editable maps
  • APIs are UI-agnostic and safe for headless usage

23.2 Sample Map Discovery

Queries

GetSampleMaps

Result<IReadOnlyList<SampleMapInfo>> GetSampleMaps();
- Returns all sample maps bundled with the SDK - Each entry contains metadata describing the sample

GetSampleMapInfo

Result<SampleMapInfo> GetSampleMapInfo(
    string sampleId
);
- Returns metadata for the specified sample map identifier

23.3 Loading and Cloning Sample Maps

Sample maps can be either loaded or cloned into a session.

  • Loading creates a map instance directly from the sample
  • Cloning creates a new editable copy of the sample map

Commands

LoadSampleMap

Result<MapHandle> LoadSampleMap(
    string sampleId
);
- Loads the specified sample map into the current session
- The returned map behaves like a regular editable map

CloneSampleMap

Result<MapHandle> CloneSampleMap(
    string sampleId
);
- Creates a new editable map cloned from the sample map
- Modifications do not affect the original sample

23.4 Sample Map Metadata

Each sample map exposes descriptive metadata to help users select appropriate examples.

SampleMapInfo

struct SampleMapInfo
{
    string Id;
    string Name;
    string Description;
    IReadOnlyList<string> CoveredFeatures;
    string IntendedUse;
}
// Describes a bundled sample map
// CoveredFeatures may include roads, junctions, signals, tram lanes, rail crossings, automation demos, etc.

23.5 Typical Sample Maps

The SDK may include example maps such as:

  • Simple two-road intersection
  • Urban four-way junction with signals
  • Tram shared-lane scenario
  • Road–rail crossing example
  • Automation demonstration map

The exact set of samples may evolve between SDK versions.

23.6 Usage Examples

List available sample maps

var samples = sampleApi.GetSampleMaps().Value;
// Enumerates all bundled sample maps

Load a sample map for experimentation

var map = sampleApi.LoadSampleMap(
    "urban.4way.basic"
).Value;
// Loads a basic urban junction sample into the session

Clone a sample map for editing

var map = sampleApi.CloneSampleMap(
    "tram.shared.lane"
).Value;
// Creates a new editable map based on a tram-related sample

23.7 Error Handling

Sample Maps APIs return structured errors in the following cases:

  • Invalid or unknown sample identifier
  • Sample content unavailable or incompatible with the current SDK version
  • Session state does not allow loading a new map

All errors follow the standard Result / Result pattern.


Final Summary

This document has described the Replimap SDK and API in detail—from high-level concepts and architecture to concrete APIs, workflows, and best practices. By providing a stable, modular, and deterministic backend, the Replimap SDK enables clients to build powerful OpenDRIVE-based tools and pipelines with confidence.