OpenCRG.jl

ASAM OpenCRG (.crg) files describe road surfaces as a curved regular grid: a reference line (position and heading as a function of the distance u along the road) plus a regular grid of elevations z over the lateral offset v from that line. OpenCRG.jl is a pure-Julia reader for these files: it parses the header, decodes the ASCII and binary payloads, applies the $ROAD_CRG_MODS modifiers and integrates the reference line into world-frame (X, Y, Z) grids. No C library is needed.

using Pkg
Pkg.add("OpenCRG")
Pkg.add("DataInterpolationsND")

Walkthrough

The examples use a sample file from the repository's test/data directory (ASAM's handmade_curved_banked_sloped.crg, a 22 m long, 3 m wide curved, banked and sloped road).

Load a file

read_crg parses a file and returns a CRGData holding all data from that file:

using OpenCRG
using DataInterpolationsND

path = joinpath(pkgdir(OpenCRG), "test", "data", "handmade_curved_banked_sloped.crg")
data = OpenCRG.read_crg(path)
CRGData (stored data, before modifiers)
  Grid: 23 × 7 points (u × v)
  u: [0.0, 22.0] m; increment: 1.0 m
  v: [-1.5, 1.5] m; increment: nonuniform
  Channels: reference-line x/y (integrated from phi), phi; elevation z; banking; slope
  z range (raw): [-0.0333333, 0.0333333] m
  Reference line closed (coincident endpoints): no
  Modifiers: none
  Options: none
  Comment: "CRG file example for road surface description (width: 3m, length: 22m)"

Evaluate the surface on a grid

road_surface_grid applies the modifiers, integrates the reference line and returns a grid (u, v, X, Y, Z).

Here, u and v are vectors of along-track and across-track distance, respectively. X, Y, Z are matrices of size (length(u), length(v)) that together define Cartesian positions of the surface of the road.

Positive v points left and negative v right, looking in the direction of increasing u. Undefined cells are NaN.

u, v, X, Y, Z = OpenCRG.road_surface_grid(data)
size(Z)
(23, 7)

Interpolate with DataInterpolationsND.jl

OpenCRG.jl only provides the grid. To evaluate it between nodes, use an interpolation package, like Interpolations.jl or DataInterpolationsND.jl. Interpolate the complete surface directly over both road-frame axes:

dimensions = (LinearInterpolationDimension(u), LinearInterpolationDimension(v))
surface = NDInterpolation(cat(X, Y, Z; dims = 3), dimensions)
surface(10.5, 0.5)  # Cartesian [x, y, z]
3-element Vector{Float64}:
 10.426222453337271
  1.046569095709622
  0.6216944249999999

The same interpolant gives the centre-line position at u = 10.5 or a point across the road at u = 10:

surface(10.5, 0.0)
3-element Vector{Float64}:
 10.479744900340215
  0.5494401000455738
  0.5722221999999999
surface(10.0, 0.5)
3-element Vector{Float64}:
 9.930611107774567
 0.9918308919767347
 0.56116665

Evaluate inside the grid (u in extrema(u), v in extrema(v)).

Restrictions

REFPOINT_U, REFPOINT_V and their _FRACTION variants are not supported (an error is thrown), REFPOINT_X/Y/Z/PHI need an exact v = 0 long-section column, GRID_NAN_MODE/GRID_NAN_OFFSET are parsed but ignored (NaN cells are not filled), and $ROAD_CRG_OPTS/$ROAD_CRG_MPRO have no effect.