> For the complete documentation index, see [llms.txt](https://multiset.gitbook.io/multiset/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://multiset.gitbook.io/multiset/basics/rest-api-docs/georeference.md).

# Georeference Map

### Georeference API

Georeference a 3D map by tying its map-local coordinate frame to real-world WGS84 coordinates. You provide a set of **control points**, each pairing a map-local position (`x, y, z` in meters) with a known geographic location (`latitude, longitude, altitude`). The server solves the map's origin and heading from these pairs, so no compass heading is required.

{% hint style="warning" %}
The `local` (3D) coordinates must be in the map's **left-handed (LHS / Unity) coordinate system**, the same frame as the `position` field returned by a successful localization query (`isRightHanded: false`). If your data is in a right-handed system (e.g. ROS, Three.js), convert it to LHS before sending.
{% endhint %}

Once a map is georeferenced, you can use GPS-based localization features such as [GeoHint](/multiset/basics/localization/geohint-in-localization.md) and receive results in geographic coordinates. See [Georeferencing Maps](/multiset/basics/georeferencing-maps.md) for the underlying concept.

{% hint style="info" %}
Provide **at least 3 control points**. They must not all lie on the same vertical line (they cannot be horizontally coincident), otherwise the heading cannot be resolved. More well-distributed points improve accuracy. Use at least 6 decimal places for latitude and longitude to reach centimetre-level accuracy.
{% endhint %}

{% openapi src="/files/M6PGwC77ySiVvF1XFlNv" path="/vps/map/{mapCode}/georeference" method="post" %}
[georeference.yaml](https://3163433004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FokTDI7QVY04Zvb1pQ8Ry%2Fuploads%2Fgit-blob-05b120459efe23c61b90c573da66d031d148af05%2Fgeoreference.yaml?alt=media)
{% endopenapi %}

#### Sample Request

```json
{
    "controlPoints": [
        {
            "name": "corner-A",
            "geo": { "latitude": 37.774912, "longitude": -122.419425, "altitude": 12.0 },
            "local": { "x": 0, "y": 0, "z": 0 }
        },
        {
            "name": "corner-B",
            "geo": { "latitude": 37.775012, "longitude": -122.419525, "altitude": 11.8 },
            "local": { "x": 10.5, "y": 0, "z": -8.2 }
        },
        {
            "name": "point-3",
            "geo": { "latitude": 37.774812, "longitude": -122.419225, "altitude": 12.3 },
            "local": { "x": -5.0, "y": 1.2, "z": 12.0 }
        }
    ],
    "solveScale": false,
    "rejectOutliers": true,
    "outlierThresholdMeters": 2.5
}
```

#### Sample Response

```json
{
    "message": "Map geo-referenced successfully",
    "mapId": "67e12d4bff7ecf561f2f8a0c",
    "origin": { "latitude": 37.77491234, "longitude": -122.41942567, "altitude": 12.045 },
    "heading": 37.5003,
    "scale": 1.0,
    "rmseMeters": 1.182,
    "horizontalRmseMeters": 0.587,
    "maxErrorMeters": 2.9,
    "numControlPoints": 4,
    "numInliers": 3,
    "inliers": ["corner-A", "corner-B", "point-3"],
    "rejected": ["outlier-point"],
    "tiltCheck": {
        "tiltAngleDeg": 0.0006,
        "tiltDirectionDeg": 66.9,
        "thresholdDeg": 1.5,
        "gravityAlignmentLikelyOk": true
    },
    "residuals": [
        {
            "name": "corner-A",
            "errorMeters": 1.15,
            "horizontalMeters": 0.53,
            "verticalMeters": 0.94,
            "isInlier": true
        }
    ]
}
```

### Reading the Result

The response reports both the solved georeference and quality metrics so you can judge the fit:

* **`origin`** and **`heading`** are the solved values applied to the map. `origin` is the WGS84 location of map-local `(0, 0, 0)`, and `heading` is degrees clockwise from true north.
* **`horizontalRmseMeters`** is the most reliable accuracy indicator. GPS altitude is noisy, so horizontal error is the number to watch.
* **`scale`** is reported only when `solveScale` is `true` and is not applied at query time. A metric scan should return a value close to `1.0`; a value far from `1.0` suggests a scaling problem in the scan.
* **`inliers`** / **`rejected`** and **`residuals`** show which control points were used and how far each landed from the final fit, so you can spot and remove bad GPS readings.
* **`tiltCheck`** verifies that the solved up axis is close to true vertical, confirming the map is gravity aligned.

{% hint style="info" %}
Georeferencing is idempotent: calling the endpoint again overwrites the map's existing georeference with the new solution.
{% endhint %}


---

# 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://multiset.gitbook.io/multiset/basics/rest-api-docs/georeference.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.
