> For the complete documentation index, see [llms.txt](https://docs.multiset.ai/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.multiset.ai/fundamentals/third-party-scans/coordinate-reference-system.md).

# Coordinate Reference System

Tell MultiSet which survey grid your E57 was exported in, so the scan lands in the right place without hand-solving control points.

## Overview

A surveyed E57 carries coordinates in some grid: a national or UTM projection, or a private site grid the plant owner maintains. The file rarely says which. Without that information MultiSet falls back to inferring a UTM zone from the location you pinned when creating the map, which is good enough for a walk-around scan and not good enough for survey work.

Declaring the grid removes the guesswork. Send it as `source.metadata.crs` on the [create-map request](/fundamentals/rest-api-docs/map-upload.md) when `fileType` is `e57`, and the scan is georeferenced directly from it.

There are two forms, and you send **exactly one**:

| Form          | Use it when                                                   | Fields                                      |
| ------------- | ------------------------------------------------------------- | ------------------------------------------- |
| **EPSG code** | The scan is in a published grid (national, UTM, state plane)  | `horizontalEpsg`, optionally `verticalEpsg` |
| **Helmert**   | The scan is in a private plant or site grid with no EPSG code | `helmert` (7 parameters)                    |

{% hint style="info" %}
This applies to E57 uploads only. A Matterport capture always arrives in its own local frame, so `crs` is rejected for `matterpak`.
{% endhint %}

## Form 1: an EPSG code

For a scan exported in a published grid. `horizontalEpsg` names the grid. `verticalEpsg` is added **only when the heights are not ellipsoidal**.

A German export in ETRS89 / UTM 32N with GPS (ellipsoidal) heights needs the horizontal code alone:

```json
{
  "source": {
    "fileType": "e57",
    "provider": "navvis",
    "metadata": {
      "crs": { "horizontalEpsg": 25832 }
    }
  }
}
```

A US export on a state plane grid with orthometric heights needs both:

```json
{
  "source": {
    "fileType": "e57",
    "provider": "leica",
    "metadata": {
      "crs": {
        "horizontalEpsg": 6424,
        "verticalEpsg": 6360
      }
    }
  }
}
```

### Choosing the horizontal code

`horizontalEpsg` must be a **projected** grid, because E57 stores Cartesian coordinates. Common choices are `25832` (ETRS89 / UTM 32N), `27700` (British National Grid) and `2056` (Swiss LV95).

A geographic code such as `4326` is rejected, with a message naming the CRS and its type. So are vendor codes outside the EPSG range, such as ESRI `102100`.

### Choosing the vertical code

Send `verticalEpsg` only when heights are orthometric, for example `3855` (EGM2008), `5701` (ODN) or `5703` (NAVD88).

{% hint style="warning" %}
**Ellipsoidal is assumed when `verticalEpsg` is absent**, and whether heights are ellipsoidal or orthometric is the one thing neither the file nor your map pin can reveal.

Get it wrong and the scan is off vertically by the local geoid undulation, which is roughly 46 m in Bavaria and roughly -90 m at Bengaluru. Everything horizontal will look perfect, so the error is easy to miss.
{% endhint %}

### Units are handled for you

The EPSG code carries its own units, so a grid in US survey feet needs nothing extra. Send the code for the grid the survey was worked in and the units are handled for you.

## Form 2: a Helmert transform

For a scan in a private grid that has no EPSG code, which is common on industrial sites where the owner maintains their own plant grid. The seven numbers come from the site owner's surveyed transform and are reused for every scan on that site.

```json
{
  "source": {
    "fileType": "e57",
    "provider": "navvis",
    "metadata": {
      "crs": {
        "helmert": {
          "tx_m": 145200.5,
          "ty_m": -4790100.25,
          "tz_m": 4195800.75,
          "rx_arcsec": 174900.0,
          "ry_arcsec": -2500.0,
          "rz_arcsec": 8760.0,
          "scale_ppm": -0.0159
        }
      }
    }
  }
}
```

### The convention

This is a 7-parameter Helmert (Bursa-Wolf) transform from the file's local grid in metres to WGS 84 ECEF (`EPSG:4978`).

| Detail         | Value                                      |
| -------------- | ------------------------------------------ |
| Convention     | **Position-vector**                        |
| Rotation order | Composed `Rz · Ry · Rx`                    |
| Translations   | Metres                                     |
| Rotations      | **Arcseconds**                             |
| Scale          | ppm, applied as `s = 1 + scale_ppm × 1e-6` |

All seven parameters are required, and no other keys are accepted.

{% hint style="warning" %}
Check the convention before you send a transform. A **coordinate-frame** Helmert uses the opposite rotation sign to a position-vector one. Published parameter sets do not always say which they are, and the two differ by enough to put a scan visibly out of place.
{% endhint %}

{% hint style="info" %}
**Heights from a Helmert are already ellipsoidal**, so `verticalEpsg` is not allowed alongside it and is rejected if sent.

Do not send an accompanying affine fit either. The two are independent solutions and must never be chained.
{% endhint %}

## What happens to the values you send

### Your declaration wins

When `crs` is present it is the source of truth, and anything the file itself declares is not used. If the file declares a grid that disagrees, yours is still applied and the difference is recorded on the map.

That is deliberate: correcting a bad export is the main reason the field exists.

### The result is sanity-checked

The resulting position is compared against the location you pinned when creating the map, and a result far from that pin is flagged on the map rather than silently accepted.

Treat that flag as a strong signal that the wrong grid, or the wrong Helmert convention, was sent.

### What lands on the map

Either form produces the same two fields the rest of the platform uses:

* `location.coordinates`, as `[longitude, latitude, altitude]` with an ellipsoidal altitude,
* `heading`, in degrees.

The map also records which of the three sources the georeference came from, so you can audit it later.

## Doing it from the portal

The Developer Portal collects the horizontal grid on the **Location** step of the create-map flow, with a list of common grids plus an **Other** option for entering an EPSG code directly. The vertical datum is offered only when you set the height reference to geoid, matching the rule above.

The Helmert form is API only. A site grid transform is not something you want retyped by hand into a form.

## Related

* [Georeference Map](/fundamentals/rest-api-docs/georeference.md), for tying an existing map to WGS 84 with ground control points instead.
* [Geo-fence](/fundamentals/georeferencing-maps/geo-fence.md), which is generated from the resulting location and heading.
* [Leica Scans](/fundamentals/third-party-scans/leica-scans.md), [NavVis Scans](/fundamentals/third-party-scans/navvis-scans.md) and [Faro Scans](/fundamentals/third-party-scans/faro-scans.md) for exporting an E57 from each vendor.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.multiset.ai/fundamentals/third-party-scans/coordinate-reference-system.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
