> 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/native-sdk/ios-swift-native/api-reference/multisetconfig.md).

# MultiSetConfig

Every MultiSetConfig property on iOS: credentials, environment, localization mode, query mode, multi frame capture, confidence and pose consistency.

## SDK Configuration

The `MultiSetConfig` struct provides centralized configuration for the MultiSet SDK localization behavior. It controls how the AR views perform localization, including timing, quality, and feature settings.

## Description

This configuration struct allows you to customize the localization behavior **before a query request is made**. Settings include the API environment, auto-localization triggers, background localization intervals, frame capture parameters, the matching pipeline used for single-frame queries, confidence thresholds, the false-positive gate, GPS integration, **localization hints** (to narrow the search for Map and MapSet localization), and UI feedback options.

Settings are supplied during SDK initialization via `MultiSet.shared.initialize(config:callback:)`. You can also change them at runtime and apply the updated configuration with [`MultiSet.shared.updateConfig(_:)`](#updating-configuration-at-runtime). The new values take effect on the **next** localization or tracking query, without re-initializing or re-authenticating. All numeric settings can be clamped to their valid ranges using the `validated()` method.

{% hint style="info" %}
`clientId`, `clientSecret` and `baseURL` are applied only at `initialize(config:callback:)`. To change any of them, call `release()` and then `initialize(...)` again.
{% endhint %}

***

## Properties

This section details the publicly accessible properties of the `MultiSetConfig` that can be configured.

### Authentication

| Property       | Type     | Default  | Description                                                                     |
| -------------- | -------- | -------- | ------------------------------------------------------------------------------- |
| `clientId`     | `String` | Required | Your MultiSet client identifier. Obtain from developer.multiset.ai/credentials. |
| `clientSecret` | `String` | Required | Your MultiSet client secret key. Obtain from developer.multiset.ai/credentials. |

### API Environment

| Property  | Type     | Default                            | Description                                                                                                                                   |
| --------- | -------- | ---------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------- |
| `baseURL` | `String` | `MultiSetConfig.productionBaseURL` | Host every SDK endpoint is built from, without a trailing slash. Override it to point the SDK at a staging, on-premise or proxied deployment. |

`MultiSetConfig.productionBaseURL` is the production API, `https://api.multiset.ai`.

This value is applied when `initialize(config:callback:)` runs, before authentication. An access token is only valid against the host that issued it, so changing the environment afterwards requires `release()` followed by a fresh `initialize(...)`. An empty or malformed value is refused and the previous host is kept.

Read `MultiSet.shared.activeBaseURL` to see which host requests are actually going to, which is useful for showing the environment a build is pointed at.

```swift
var config = MultiSetConfig.default(
    clientId: "your_client_id",
    clientSecret: "your_client_secret",
    mapCode: "your_map_code"
)
config.baseURL = "https://staging-api.multiset.ai"   // no trailing slash needed

MultiSet.shared.initialize(config: config, callback: delegate)
```

### Map Configuration

| Property     | Type     | Default | Description                                                                           |
| ------------ | -------- | ------- | ------------------------------------------------------------------------------------- |
| `mapCode`    | `String` | `""`    | Single map identifier for localization. Use either this or `mapSetCode`.              |
| `mapSetCode` | `String` | `""`    | MapSet identifier for localizing against multiple maps. Use either this or `mapCode`. |

### Localization Mode

| Property           | Type               | Default       | Description                                                                                                                         |
| ------------------ | ------------------ | ------------- | ----------------------------------------------------------------------------------------------------------------------------------- |
| `localizationMode` | `LocalizationMode` | `.multiFrame` | The capture strategy: `.singleFrame` for quick single-image capture, or `.multiFrame` for multi-image capture with better accuracy. |
| `queryMode`        | `QueryMode`        | `.vps1`       | Matching pipeline for **single-frame** queries. Not sent in `.multiFrame` mode, which always runs on VPS-1.                         |

#### Query Mode (single-frame only)

Single-frame localization can run against either matching pipeline:

| Value   | Name                | Behavior                                                                     |
| ------- | ------------------- | ---------------------------------------------------------------------------- |
| `.vps1` | VPS-1 (Standard)    | Standard matching. Fastest response, best for well-mapped areas.             |
| `.vps2` | VPS-2 (Deep Search) | Deep search. Slower, but recovers a pose in harder or sparsely mapped areas. |

```swift
config.queryMode = .vps2
```

The mode can also be changed on an already-initialized SDK, taking effect on the next run:

```swift
MultiSet.shared.setQueryMode(.vps2)
```

Multi-frame localization always uses VPS-1, so this value is ignored in `.multiFrame` mode.

### Localization Behavior

| Property                        | Type    | Default | Description                                                                                                                                                  |
| ------------------------------- | ------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `autoLocalize`                  | `Bool`  | `true`  | Whether to automatically start localization when the AR session begins. If `false`, the user must manually tap the capture/localize button.                  |
| `backgroundLocalization`        | `Bool`  | `true`  | Whether to continue localization in the background after the first success. Helps maintain accurate positioning over time.                                   |
| `bgLocalizationDurationSeconds` | `Float` | `30.0`  | The time interval in seconds between background localization attempts. Only used when `backgroundLocalization` is `true`. Valid range: **15 - 180 seconds**. |
| `relocalization`                | `Bool`  | `true`  | Whether to enable relocalization when AR tracking is lost. Automatically triggers localization when the AR tracking state changes to paused or stopped.      |
| `firstLocalizationUntilSuccess` | `Bool`  | `true`  | Keep trying until the first localization succeeds. If `true`, failed localizations will silently retry until one succeeds.                                   |

### Multi-Frame Capture Settings

| Property                 | Type  | Default | Description                                                                                                                                         |
| ------------------------ | ----- | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |
| `numberOfFrames`         | `Int` | `4`     | The number of frames to capture for multi-frame localization. More frames = better accuracy but longer capture time. Valid range: **4 - 6 frames**. |
| `frameCaptureIntervalMs` | `Int` | `500`   | The interval between frame captures in milliseconds. Allows user movement between frames for better coverage. Valid range: **300 - 800 ms**.        |

### Confidence Settings

| Property              | Type    | Default | Description                                                                                                                                         |
| --------------------- | ------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |
| `confidenceCheck`     | `Bool`  | `false` | Whether to check confidence threshold before accepting localization. If `true`, localizations with confidence below the threshold will be rejected. |
| `confidenceThreshold` | `Float` | `0.3`   | Minimum confidence score to accept a localization result. Only used when `confidenceCheck` is `true`. Valid range: **0.2 - 0.8**.                   |

### Pose Consistency Settings

The confidence score reports how sure the server is about a match, not whether the match is in the right place. In a visually repetitive space (a corridor of identical doors, a row of matching desks) the server can return a **confident pose for the wrong location**, and the mesh visibly jumps several metres.

The pose consistency check catches this by comparing each result against the device's own AR trajectory. Every fix in a session measures the same map-to-session transform, so a result that moves it further than ARKit could plausibly have drifted is not physically possible. Such a result is discarded, the AR scene is left exactly as it was, and [`onLocalizationFalsePositive(info:)`](/native-sdk/ios-swift-native/api-reference/multisetcallback.md) is called instead of `onLocalizationSuccess`.

| Property                   | Type    | Default | Description                                                                                                                            |
| -------------------------- | ------- | ------- | -------------------------------------------------------------------------------------------------------------------------------------- |
| `poseConsistencyCheck`     | `Bool`  | `false` | Whether to reject localization results that contradict the device's own AR trajectory.                                                 |
| `poseConsistencyThreshold` | `Float` | `10.0`  | Tolerance in metres before a result counts as contradicting. Only used when `poseConsistencyCheck` is `true`. Valid range: **3 - 30**. |

```swift
config.poseConsistencyCheck = true
config.poseConsistencyThreshold = 10
```

Lower the threshold in small, tightly mapped spaces where a real fix should never move much. Raise it in large outdoor maps, or when long gaps between fixes allow more tracker drift.

The check maintains its own reference pose automatically, including across tracking interruptions. Call `MultiSet.shared.resetPoseConsistencyReference()` when the user asks to start over, or after a run of rejections the user believes are wrong. The first result after that call is accepted without being checked and becomes the new reference.

### GPS Settings

| Property                   | Type   | Default | Description                                                                                                                                                    |
| -------------------------- | ------ | ------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `passGeoPose`              | `Bool` | `false` | Whether to send GPS coordinates as a hint to improve localization. Requires location permission. Useful for outdoor or large-scale maps.                       |
| `geoCoordinatesInResponse` | `Bool` | `false` | Whether to include geo-coordinates in the localization response. Useful if you need the world position of localized objects.                                   |
| `hintRadius`               | `Int`  | `25`    | Search radius in meters for spatial filtering. Only applies when a geo hint or `hintPosition` is provided; sent when greater than 0. Valid range: **1 - 100**. |
| `use2DFiltering`           | `Bool` | `false` | When `true`, skips altitude (Y-axis) in spatial filtering, using only horizontal distance (X and Z). Only applies when a geo hint is provided.                 |

### Localization Hints

These hints narrow the search space for **Map** and **MapSet** localization, improving speed and accuracy in large or visually repetitive environments. They are most useful to set (or adjust) at runtime, right before a query. See [Updating Configuration at Runtime](#updating-configuration-at-runtime).

| Property          | Type       | Default | Description                                                                                                                                                        |
| ----------------- | ---------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `hintMapCodes`    | `[String]` | `[]`    | Map codes that narrow the candidate maps during **MapSet** localization. Only sent when localizing a MapSet; each code is sent as a separate `hintMapCodes` field. |
| `hintPosition`    | `String`   | `""`    | Positional hint to seed localization, in `"X,Y,Z"` format. Sent when non-empty.                                                                                    |
| `hintFloorHeight` | `String`   | `""`    | Floor/ceiling height hint, in `"floor,ceiling"` format (e.g. `"0,5"`). Sent when non-empty.                                                                        |

### UI Settings

| Property            | Type   | Default | Description                                                                                                     |
| ------------------- | ------ | ------- | --------------------------------------------------------------------------------------------------------------- |
| `showAlerts`        | `Bool` | `true`  | Whether to show UI alerts (toasts) for localization status. Shows success/failure messages to the user.         |
| `meshVisualization` | `Bool` | `true`  | Whether to show 3D mesh overlay after successful localization. The mesh helps visualize the mapped environment. |

### Image Quality Settings

| Property       | Type  | Default | Description                                                                                                                                        |
| -------------- | ----- | ------- | -------------------------------------------------------------------------------------------------------------------------------------------------- |
| `imageQuality` | `Int` | `90`    | JPEG quality for captured images sent to the localization API. Higher quality = better accuracy but larger upload size. Valid range: **50 - 100**. |

### Object Tracking Settings

| Property                          | Type       | Default | Description                                                                                                                           |
| --------------------------------- | ---------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------- |
| `objectCodes`                     | `[String]` | `[]`    | Array of object codes to track. Obtain from the MultiSet dashboard. Maximum **10** codes.                                             |
| `autoObjectTracking`              | `Bool`     | `true`  | Whether to automatically start object tracking when the AR session is ready.                                                          |
| `backgroundObjectTracking`        | `Bool`     | `true`  | Whether to re-send tracking requests at regular intervals after first success.                                                        |
| `bgObjectTrackingDurationSeconds` | `Float`    | `15.0`  | Interval in seconds between background object tracking requests. Valid range: **5 - 30 seconds**.                                     |
| `restartObjectTracking`           | `Bool`     | `true`  | Whether to re-track when AR tracking state is lost or paused.                                                                         |
| `objectTrackingCaptureDelay`      | `Float`    | `1.0`   | Delay in seconds before capturing the frame after tracking is triggered. Gives users time to aim. Valid range: **0.5 - 3.0 seconds**. |
| `firstObjectTrackingUntilSuccess` | `Bool`     | `true`  | If `true`, failed tracking attempts will silently retry until one succeeds, without triggering `onObjectTrackingFailure`.             |

***

## Computed Properties

| Property                         | Type           | Description                                                          |
| -------------------------------- | -------------- | -------------------------------------------------------------------- |
| `activeMapType`                  | `MapType`      | Returns `.map` or `.mapSet` based on which code is configured.       |
| `activeMapCode`                  | `String`       | Returns the active map code (either `mapCode` or `mapSetCode`).      |
| `hasCredentials`                 | `Bool`         | Returns `true` if both `clientId` and `clientSecret` are configured. |
| `hasMapConfiguration`            | `Bool`         | Returns `true` if either `mapCode` or `mapSetCode` is configured.    |
| `hasObjectTrackingConfiguration` | `Bool`         | Returns `true` if `objectCodes` is non-empty.                        |
| `frameCaptureIntervalSeconds`    | `TimeInterval` | Returns `frameCaptureIntervalMs` converted to seconds.               |
| `bgLocalizationDuration`         | `TimeInterval` | Returns `bgLocalizationDurationSeconds` as `TimeInterval`.           |

***

## Factory Methods

Each factory method returns a `MultiSetConfig` preset for a common localization strategy.

### default(clientId:clientSecret:mapCode:)

Multi-frame localization with every other setting left at its default.

```swift
let config = MultiSetConfig.default(
    clientId: "your_client_id",
    clientSecret: "your_client_secret",
    mapCode: "your_map_code"
)
```

### singleFrame(clientId:clientSecret:mapCode:)

Single-image localization: captures one frame, with auto and background localization disabled.

```swift
let config = MultiSetConfig.singleFrame(
    clientId: "your_client_id",
    clientSecret: "your_client_secret",
    mapCode: "your_map_code"
)
```

### multiFrame(clientId:clientSecret:mapCode:)

Multi-image localization for higher accuracy.

```swift
let config = MultiSetConfig.multiFrame(
    clientId: "your_client_id",
    clientSecret: "your_client_secret",
    mapCode: "your_map_code"
)
```

### continuous(clientId:clientSecret:mapCode:)

Aggressive re-localization, re-localizing at 15-second intervals.

```swift
let config = MultiSetConfig.continuous(
    clientId: "your_client_id",
    clientSecret: "your_client_secret",
    mapCode: "your_map_code"
)
```

***

## Methods

### validated()

Returns a new configuration with all numeric settings clamped to their valid ranges.

**Declaration**

```swift
func validated() -> MultiSetConfig
```

**Description**

Calling this method returns a new configuration with all values clamped to acceptable bounds. This ensures that all configuration values are within acceptable ranges before they are used by the SDK.

**Validation Rules:**

| Property                          | Valid Range             |
| --------------------------------- | ----------------------- |
| `bgLocalizationDurationSeconds`   | 15 - 180                |
| `numberOfFrames`                  | 4 - 6                   |
| `frameCaptureIntervalMs`          | 300 - 800               |
| `confidenceThreshold`             | 0.2 - 0.8               |
| `poseConsistencyThreshold`        | 3 - 30                  |
| `hintRadius`                      | 1 - 100                 |
| `imageQuality`                    | 50 - 100                |
| `objectCodes`                     | Truncated to 10 entries |
| `bgObjectTrackingDurationSeconds` | 5 - 30                  |
| `objectTrackingCaptureDelay`      | 0.5 - 3.0               |

**Example**

```swift
var config = MultiSetConfig(
    clientId: "id",
    clientSecret: "secret",
    mapCode: "map",
    numberOfFrames: 10  // Outside valid range
)

// validated() will clamp numberOfFrames to 6
config = config.validated()
```

***

## Updating Configuration at Runtime

Configuration is supplied once at initialization, but you can change the **Map / MapSet localization settings on the fly** and apply them **before the next query request** using `MultiSet.shared.updateConfig(_:)`. This is the recommended way to adjust behavior (auto-localize, confidence thresholds, background intervals, localization hints, object-tracking behavior) between queries without tearing down the SDK.

### updateConfig(\_:)

**Declaration**

```swift
func updateConfig(_ config: MultiSetConfig)
```

**Description**

Applies an updated configuration to an already-initialized SDK **without re-authenticating**. The new behavioral settings take effect on the **next** localization / tracking query; a run that is already in flight is unaffected. Credentials, `baseURL` and authentication state are preserved. To change any of them, call `release()` followed by `initialize(config:callback:)` instead. The call is a no-op if the SDK has not been initialized yet.

**Example**

```swift
// Start from the current configuration, adjust MapSet hints, then apply before querying
var config = MultiSet.shared.config ?? SDKConfig.buildConfig()

config.passGeoPose = true
config.hintRadius = 40
config.hintMapCodes = ["MAP_A", "MAP_B"]   // narrow MapSet candidates
config.confidenceThreshold = 0.5

MultiSet.shared.updateConfig(config)        // takes effect on the next query
MultiSet.shared.localize()
```

> The updated values take effect on the next `localize()` or object-tracking query, so there is no need to re-initialize or re-authenticate the SDK.

### Targeted Setters

Two settings have dedicated setters for the common case of changing just that one value between runs. Both take effect on the next localization run and neither re-authenticates.

```swift
MultiSet.shared.setLocalizationMode(.singleFrame)
MultiSet.shared.setQueryMode(.vps2)          // single-frame only
```

### In-App Settings Screen

The sample app exposes a **Configuration** screen (the gear icon on the [LandingView](/native-sdk/ios-swift-native/sample-views/landingview.md)) that edits these same properties at runtime. It is backed by a `ConfigStore` that persists values across launches via `UserDefaults`, and it calls `updateConfig(_:)` on **Save** / **Reset**, so changes apply to the running SDK immediately, before your next localization or object-tracking query.

***

## Usage Examples

### Basic Configuration

```swift
// Configure for quick, automatic localization
let config = MultiSetConfig(
    clientId: clientId,
    clientSecret: clientSecret,
    mapCode: mapCode,
    autoLocalize: true,
    backgroundLocalization: true,
    showAlerts: true
)

MultiSet.shared.initialize(config: config, callback: delegate)
```

***

## Configuration Flow

```
1. Create MultiSetConfig with desired properties
         |
2. Optionally call config.validated()
         |
3. Call MultiSet.shared.initialize(config:callback:)
         |
4. SDK reads configuration during initialization
         |
5. Localization behavior follows configuration
         |
6. (Optional) Change properties and call MultiSet.shared.updateConfig(_:)
   to apply the new settings before the next query
```

***

## Best Practices

1. **Always validate configuration** by calling `validated()` after modifying settings to ensure values are within valid ranges.
2. **Apply runtime changes with `updateConfig(_:)`** rather than re-initializing. It updates the live SDK before the next query without a re-authentication round-trip.
3. **Set localization hints (`hintMapCodes`, `hintPosition`, `hintRadius`)** before a MapSet query to narrow the candidate maps in large or repetitive spaces.
4. **Enable `poseConsistencyCheck`** in visually repetitive spaces, where a confidence threshold alone cannot tell a confident match from a confident match in the wrong place.
5. **Try `queryMode = .vps2`** for single-frame queries in sparsely mapped or difficult areas, accepting the slower response.
6. **Disable `firstLocalizationUntilSuccess`** when using `passGeoPose` and `geoCoordinatesInResponse` together, as geo-based failures should be reported to the user.
7. **Increase `numberOfFrames`** for environments with sparse or repetitive features.
8. **Enable `backgroundLocalization`** for applications that need to maintain accurate positioning over time.
9. **Use higher `imageQuality`** for complex environments but be mindful of network bandwidth.

***

## Related

* [MultiSetCallback](/native-sdk/ios-swift-native/api-reference/multisetcallback.md)
* [LocalizationResult](/native-sdk/ios-swift-native/api-reference/localizationresult.md)
* [LandingView](/native-sdk/ios-swift-native/sample-views/landingview.md)
* [ARLocalizationView](/native-sdk/ios-swift-native/sample-views/arlocalizationview.md)
* [ARObjectTrackingView](/native-sdk/ios-swift-native/sample-views/arobjecttrackingview.md)


---

# 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/native-sdk/ios-swift-native/api-reference/multisetconfig.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.
