# LumiScan Calibration 2.0.0.8 – complete documentation

> All pages of the LumiScan Calibration 2.0.0.8 manual (language: en) by HD Vision Systems GmbH, in navigation order. Each page starts with a level-1 heading followed by its URL; cite that URL. Manual: https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/

# Description – LumiScan Calibration

URL: https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/lumiscan-calibration/description.html

LumiScan Calibration is an application for converting 2D image coordinates into corresponding 3D coordinates on a calibrated plane. This allows position information detected in camera images to be mapped to real-world coordinates, for example for robotic bin picking, object placement, and similar automation tasks.

The conversion is based on calibration data provided as a TIFF file. The application uses configurable transformation modules to map image coordinates to 3D coordinates and supports different interpolation methods for determining values between calibrated points.

LumiScan Calibration runs on ctrlX OS (ctrlX CORE or ctrlX IPC), where it is installed from the App Store, and on a PC with Windows 11 or Ubuntu 24.04. The application is configured using JSON settings files, while the transformation functions, input coordinates, output coordinates, and status information are accessed through the Data Layer: the ctrlX Data Layer on ctrlX OS, LumiScan Keryx on a PC.

What is the same for every LumiScan app - how addresses are built, the handshake, execute and stream call patterns, status codes, settings and tools - is described in the [LumiScan Keryx](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/index.html) manual. This manual covers only what is specific to LumiScan Calibration; the pages of this manual describe its own nodes.

A module converts the points a program writes, on request: through a ready/request handshake, or with a single write to an `execute` method. From v2.1.0, a module can also convert a stream of points as they arrive (experimental): the points of a PLC array, or the positions in another LumiScan application’s result, such as the objects AI Object Matching finds on a camera’s image stream. See [Transforming a Stream (Experimental)](https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/lumiscan-calibration/streams.html).

LumiScan Cockpit does not show LumiScan Calibration: a module produces coordinates, not an image.

# Requirements – LumiScan Calibration

URL: https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/lumiscan-calibration/requirements.html

## Platform

LumiScan Calibration runs on:

- **ctrlX OS** (ctrlX CORE or ctrlX IPC), where it is installed from the App Store. Configuration, control, coordinates and status are exchanged through the ctrlX Data Layer.
- **a PC** with Windows 11 or Ubuntu 24.04. Configuration, control, coordinates and status are exchanged through LumiScan Keryx, the Data Layer of HD Vision Systems for PCs.

The node addresses are the same on both. See [ctrlX Data Layer and LumiScan Keryx](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/platforms.html).

## Licence {#licence}

How LumiScan Calibration is licensed depends on where you bought it and where it runs:

| Bought from | Runs on | Licensing |
| --- | --- | --- |
| HD Vision Systems | Windows 11 or Ubuntu 24.04 | The licence is held on your LumiScan Key. It is a one-time purchase and needs no renewal.<br><br>[Licensing path: bought from HD Vision Systems](https://docs.hdvisionsystems.com/en/lumiscan-licensing/1.0.4/path-hdvs.html) |
| ctrlX Store | Windows 11 | The licence is held in ctrlX WORKS. The LumiScan Key is required in addition; it protects the software against reverse engineering.<br><br>[Licensing path: ctrlX Store, Windows](https://docs.hdvisionsystems.com/en/lumiscan-licensing/1.0.4/path-ctrlx-windows.html) |
| ctrlX Store | ctrlX OS (ctrlX CORE or IPC) | ctrlX licence `SWL-W-XCx-CALIBRATExHDVSx-V2NN`, one licence per app instance.<br><br>[Licensing path: ctrlX Store, ctrlX OS](https://docs.hdvisionsystems.com/en/lumiscan-licensing/1.0.4/path-ctrlx-os.html) |

Each device on which LumiScan Calibration runs at the same time needs its own LumiScan Key. Keys can be exchanged between devices.

How to install CodeMeter Runtime and how to request, renew and move licences is described in [LumiScan Licensing](https://docs.hdvisionsystems.com/en/lumiscan-licensing/1.0.4/index.html).

On ctrlX OS, the application shuts down shortly after starting if the licence is missing; the reason is written to the system log. If the licence is lost while the application runs, every module reports status `-4` (`missingLicense`) and runs no function until it is back.

## Calibration Data

LumiScan Calibration requires a calibration data file in TIFF format for each module.

The TIFF file contains the 2D-to-3D mapping used to convert image coordinates into corresponding 3D coordinates on the calibrated plane. The file is generated from calibration images and provided by HD Vision Systems.

For information on obtaining the required calibration data, see [Tiff File](https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/lumiscan-calibration/tiff-file.html).

## Streams (experimental)

A remap stream reads another application’s result through the compiled schemas LumiScan Calibration ships. A plain stream needs a node that holds a float32 or float64 array, for example a PLC variable. See [Transforming a Stream (Experimental)](https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/lumiscan-calibration/streams.html).

# General Concept of Handshake – LumiScan Calibration

URL: https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/lumiscan-calibration/general-concept-of-handshake.html

Each function of a module can be started with a handshake on two nodes, `ready` and `request` ([Table 1](https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/lumiscan-calibration/general-concept-of-handshake.html#table-1-handshake-address)). A function can also be started with a single write to its `execute` method instead, see [Execute methods](https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/lumiscan-calibration/functionalities.html#execute). The handshake of all LumiScan applications is described in [Handshake](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/handshake.html); LumiScan Calibration follows its sequence exactly.

**Table 1. Table 1: General Concept of Handshake: Addresses**

| Address | Description |
| --- | --- |
| `<module address>/control/<function name>/ready` | Read-Only. Set by the module: `true` when the function can be started. |
| `<module address>/control/<function name>/request` | Writable. Set by the client to start the function. |

`<module address>` is `hdvisionsystems/lumiscan-calibration/<module name>`, and the function name is `transform` or `reset`. A function’s inputs are under `<module address>/input/` and its results under `<module address>/output/`. For each function’s nodes, see [Table 2](https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/lumiscan-calibration/functionalities.html#table-2-functionality-addresses).

## Running a function {#functionality-execution}

1. Wait until `control/<function name>/ready` is `true`.
2. If the function has inputs, write them, for example `input/x-coordinate` and `input/y-coordinate`.
3. Set `control/<function name>/request` to `true`.
4. Wait until `control/<function name>/ready` is `false`: the module has seen the request.
5. Set `control/<function name>/request` to `false`.
6. The module runs the function.
7. When the function has finished, `control/<function name>/ready` is `true` again.
8. Read `control/status/code`, and the results under `output/`.

**Functionality Execution Steps**

```mermaid
%% The ready/request handshake. Rendered by Mermaid in the browser; edit and preview at https://mermaid.live
sequenceDiagram
  autonumber
  participant C as Client (PLC or program)
  participant M as Module
  M-->>C: ready = true: the function can be started
  C->>M: request = true
  M-->>C: ready = false: the request was seen
  C->>M: request = false
  Note over M: runs the function
  M-->>C: ready = true: the function has finished
  C->>M: read control/status/code and output/
```

Good to know:

- The module waits for `request` to fall for as long as it takes. It has no timeout, because a request still `true` after one would be read as a new request.
- A reset requested while a transform waits for its `request` to fall takes precedence: the transform is dropped, and the reset runs next.
- An error status stays on `control/status/code` until the next request.

> [!IMPORTANT]
> Make sure that only one process writes `control/<function name>/request`: if several processes change it independently, the module may miss a request. See [Handshake: Rules](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/handshake.html#rules).
>
> A program that cannot coordinate with others can use the `execute` methods instead, which refuse a second call while one runs.

# Functionalities – LumiScan Calibration

URL: https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/lumiscan-calibration/functionalities.html

Each module configuration file listed in the application settings is one **module**. Its nodes are at `hdvisionsystems/lumiscan-calibration/<module name>/`, where the module name is the name of the module configuration file without `.json`, in lower case. A module offers two functions:

- `transform` converts 2D image coordinates into 3D coordinates with the module’s lookup table.
- `reset` reads the module configuration file and its lookup table again.

Each function can be started in two ways, and both lead to the same result:

- the **ready/request handshake**, see [General Concept of Handshake](https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/lumiscan-calibration/general-concept-of-handshake.html);
- a single write to its **`execute`** method, see [Execute methods](https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/lumiscan-calibration/functionalities.html#execute).

A module can also transform a stream of points as they arrive, see [Transforming a Stream (Experimental)](https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/lumiscan-calibration/streams.html).

## Data Layer {#data-layer}

LumiScan Calibration offers its functions on the Data Layer under `hdvisionsystems/lumiscan-calibration`.

On ctrlX OS (ctrlX CORE or ctrlX IPC), LumiScan Calibration uses the [ctrlX Data Layer](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/ctrlx-data-layer.html).

On a PC with Windows 11 or Ubuntu 24.04, LumiScan Calibration uses [LumiScan Keryx](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/keryx.html).

The node addresses, types and call patterns are the same on both. LumiScan Calibration offers:

- [ready/request handshakes](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/handshake.html)
- [execute methods](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/execute.html)
- a [stream](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/streams.html) subscription to one source (experimental)

How addresses are built, how to call functions, the status codes and the tools are described in [LumiScan Keryx](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/index.html).

## Addresses {#addresses}

All addresses below start with `hdvisionsystems/lumiscan-calibration/<module name>/`.

**Table 1. Table 2: Functionality Addresses**

| Function | Address | Permission | Meaning |
| --- | --- | --- | --- |
| transform | `control/transform/ready` | Read-Only | `true` when a transform can be requested. |
| transform | `control/transform/request` | Writable | Requests a transform, see the handshake. |
| transform | `control/transform/execute` | Method | Runs one transform and returns when it has finished. |
| reset | `control/reset/ready` | Read-Only | `true` when a reset can be requested. |
| reset | `control/reset/request` | Writable | Requests a reset, see the handshake. |
| reset | `control/reset/execute` | Method | Runs one reset and returns when it has finished. |
| status | `control/status/code` | Read-Only | The status of the last function, see [Status Code Values](https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/lumiscan-calibration/functionalities.html#status-code-values). |
| status | `control/status/text` | Read-Only | The same status as text. |
| input | `input/x-coordinate` | Writable | The `x` (pixel column) of one point. |
| input | `input/y-coordinate` | Writable | The `y` (pixel row) of one point. |
| input | `input/x-coordinate-array` | Writable | The `x` of each of several points. |
| input | `input/y-coordinate-array` | Writable | The `y` of each of several points, as many as `input/x-coordinate-array` has. |
| output | `output/x-coordinate`, `output/y-coordinate`, `output/z-coordinate` | Read-Only | The 3D coordinates of the point on `input/x-coordinate` and `input/y-coordinate`. |
| output | `output/x-coordinate-array` | Read-Only | The `x` of each point of the input arrays, in their order. |
| output | `output/y-coordinate-array` | Read-Only | The `y` of each point of the input arrays. |
| output | `output/z-coordinate-array` | Read-Only | The `z` of each point of the input arrays. |
| output | `output/timestamp/seconds` | Read-Only | When the last transform finished, in whole seconds, by the clock of the device. |
| output | `output/timestamp/milliseconds` | Read-Only | The milliseconds of that time, 0 to 999. |
| output | `output/timestamp/macroseconds` | Read-Only | The microseconds of that time, 0 to 999. |
| output | `output/package-identifier` | Read-Only | Counts the transforms that finished, starting from `1`. A new value means new outputs. |
| output | `output/source` | Read-Only | The module name. |
| stream | `control/subscribe/…`, `control/unsubscribe/…`, `setting/stream/…` |   | On every module; without a `stream` section, a module streams plain. See [Transforming a Stream](https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/lumiscan-calibration/streams.html#addresses). |

The application itself reports at `hdvisionsystems/lumiscan-calibration/system/`:

- `found-modules`: the names of the modules it serves.
- `status-text`: `"Initialized"` once it serves its modules, or why it serves none.
- `meta/subscription-schema`: what the node a module’s stream subscribes to may hold, as a JSON Schema. See [What a source may hold](https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/lumiscan-calibration/streams.html#subscription-schema).

## Transforming points {#transform}

One `transform` converts the point on `input/x-coordinate` and `input/y-coordinate` **and** every point of `input/x-coordinate-array` and `input/y-coordinate-array`. Leave the arrays empty to convert one point only.

1. Write the inputs.
2. Start the transform with the handshake or with `control/transform/execute`.
3. When it has finished, read the outputs. `output/package-identifier` has grown by one.

Good to know:

- `control/transform/ready` is `false` while the module has no lookup table. Correct the module configuration file or the TIFF file, then reset the module.
- If the two input arrays differ in length, the status is `-10001` (`inputXYSizeNotEqual`). The single point is converted, but the output arrays, the timestamp and `output/package-identifier` are not written.
- A point outside the lookup table is not reported as an error: the result is a value from the edge of the table. Keep the points within the image the table was made for.

## Reloading the settings {#reset}

A `reset` reads the module configuration file and the TIFF file it names again, and the next transform uses them. No restart of the application is needed. The reset also reads the `stream` section again, its source and stream mode included, and sets `control/subscribe/input/…` to it.

- If the reset succeeds, the status is `0` and `control/transform/ready` is `true`.
- If it fails, for example because the TIFF file is missing, the status is `-2` (`invalidSetting`) and the module has **no** lookup table: `control/transform/ready` stays `false` until a reset succeeds. The log says why. The module does not keep transforming with the old table, so that a corrected file is never mixed with an outdated one.
- A changed `stream` section is applied with the reset, see [Configuring a stream](https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/lumiscan-calibration/streams.html#configuring).
- Loading the example table took about 30 ms on a PC. A larger table, or a ctrlX CORE, can take longer.

## Execute methods {#execute}

`control/transform/execute` and `control/reset/execute` run their function once and return when it has finished. Write any value to them. The function uses the same inputs and writes the same outputs and status as the handshake.

Whether the function could be started at all is reported by the write itself. A rejected write is never queued. The results are named below as on the ctrlX Data Layer; LumiScan Keryx reports the same results under its own names, see [Results of a method call](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/status-codes.html#method-results):

| Result | Meaning | What to do |
| --- | --- | --- |
| OK | The function ran. Its outcome is on `control/status/code`. | Read the status and the outputs. |
| `DL_TOO_MANY_OPERATIONS` | Another transform or reset of this module is running, through the handshake or another `execute`. | Retry. The same write succeeds once the running function finishes. |
| `DL_INVALID_OPERATION_MODE` | `transform`: the module has no lookup table, or no licence. `reset`: no licence. | Do not retry in a loop. Correct the cause first: for a missing table, correct the files and reset. |
| `DL_RESOURCE_UNAVAILABLE` | The application is stopping. | Wait for the application to start again. |

A running stream never makes an `execute` busy.

## Status Code Values {#status-code-values}

`control/status/code` and `control/status/text` report the outcome of the last function. An error status stays until the next request: a module that waits for its next request does not overwrite it with `0`. Codes `0` to `-5` are the module status codes shared by the LumiScan applications, see [Status Codes and Results](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/status-codes.html#module-status); `-10001` is LumiScan Calibration’s own.

**Table 2. Table 3: Status Code Values**

| Status Code | String | Meaning |
| --- | --- | --- |
| 0 | `"ready"` | The last function completed successfully, and the module is ready for the next one. |
| 1 | `"settingUp"` | The module is being initialized. |
| 2 | `"running"` | A function is running. |
| 3 | `"waitingForClient"` | The module waits for the client to set `request` back to `false`. |
| -1 | `"undefinedError"` | An unspecified error occurred. |
| -2 | `"invalidSetting"` | The module configuration file or its TIFF file could not be loaded, so the module has no lookup table. Correct them, then reset the module. |
| -3 | `"invalidInput"` | One or more input values are invalid. |
| -4 | `"missingLicense"` | The required licence is not available. |
| -5 | `"restartRequired"` | The settings files were changed on the Data Layer: restart the application. See [Settings on the Data Layer](https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/lumiscan-calibration/settings-on-the-data-layer.html#restart-required). |
| -10001 | `"inputXYSizeNotEqual"` | `input/x-coordinate-array` and `input/y-coordinate-array` differ in length. |

# Transforming a Stream (Experimental) – LumiScan Calibration

URL: https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/lumiscan-calibration/streams.html

> [!IMPORTANT]
> The stream is **experimental** (from v2.1.0). Its nodes and settings may still change. Use it for evaluation, and verify it with your setup before relying on it.

The `transform` function converts the points your program writes, one request at a time. A stream works the other way round. The module subscribes to one Data Layer node, its **source**, and transforms **every update** of it as it arrives. The source is named in two parts: the **folder** it is in (`address`), and the **node** in that folder (the step’s `node`). It publishes the result on `<module name>/control/subscribe/output/stream/points`, with the update’s lineage - where its points came from - and on `<module name>/control/subscribe/output/stream/plain-points` as a plain array, and your program subscribes to one of them.

A stream can read its points in two ways. The step in the `onEntry` list of the module’s `stream` section says which:

- **plain** (no step, or a `plain` step): the node holds the points themselves, as one array of numbers: `x0,y0,x1,y1,…` or `x0,y0,z0,x1,y1,z1,…`. A PLC array is a typical source.
- **remap** (a `remap` step): the node holds the result of another application as a flatbuffer - by default the image-stream result of LumiScan AI Object Matching. The step names the list of elements in it, and the fields that hold each element’s `x` and `y`.

Either way, the module publishes one triplet per point, `x,y,z`, in the order of the source (see [The points](https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/lumiscan-calibration/streams.html#points)). A plain stream can read another module’s points, so modules chain (see [Chaining modules](https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/lumiscan-calibration/streams.html#chaining)).

A module has one source, transformed with the module’s one lookup table. To transform two sources, use two modules - also for two sources in the same camera’s image, which then share the same lookup table file.

> [!NOTE]
> A remap stream transforms every result of its source, whichever camera it came from: a filter reads fields of the elements, not the result’s lineage. To transform the results of several cameras with each camera’s own table, let each camera have an AI Object Matching module of its own, and each of those a Calibration module.

## Configuring a stream {#configuring}

Every module has the stream nodes, and every module can stream. The `stream` section of its module configuration file names the source and holds stream mode. Its `onEntry` list holds the steps that read each update of the source. A module whose file has no `stream` section streams plain, and `control/subscribe/execute` makes the section when it saves the source.

The `stream` section has the same general keys in every LumiScan application that subscribes to a stream. Only the steps differ:

```json
"stream": {
    "enable": true,
    "address": "hdvisionsystems/lumiscan-ai-object-matching/example/control/subscribe/output/stream",
    "queueSize": 64,
    "keepLatestOutput": false,
    "onEntry": [
        { "kind": "remap", "node": "result", "array": "instances",
          "x": "oriented_bounding_box.center_x", "y": "oriented_bounding_box.center_y" }
    ]
}
```

| Key | Required | Meaning |
| --- | --- | --- |
| `enable` | No | Stream mode: `true` runs the stream from the start of the application, without anyone calling `control/subscribe/execute`. Needs an `address`. Left out, or `false`: the stream is off until `control/subscribe/execute` switches it on. |
| `address` | With `enable` | The folder of the node to subscribe to; the step’s `node` names the node in it. It is used exactly as written: its case is kept, which a PLC symbol needs. For a plain stream the node must hold a float32 or float64 array, for a remap stream a flatbuffer of the step’s `schema`. Left out, or empty, to subscribe at run time. An address that ends in the step’s node - the node itself, not its folder - is subscribed to with the node added once more, which fails: the log warns and names the folder to write. |
| `tag` | No | The tag on the points the module publishes: the module’s step in their lineage carries it, so a client further on sees which module transformed them. Left out, or empty: the module name. See [The lineage of the points](https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/lumiscan-calibration/streams.html#lineage). |
| `queueSize` | No | How many updates may wait to be transformed: 1 to 4096, 64 by default. See [The queue](https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/lumiscan-calibration/streams.html#queue). |
| `keepLatestOutput` | No | `true` also writes the points of each update to the module’s regular output. See [Keeping the latest output](https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/lumiscan-calibration/streams.html#keep-latest-output). `false` by default. |
| `onEntry` | No | The steps applied to each update as it arrives, in order, each an object with a `kind`: a [`plain`](https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/lumiscan-calibration/streams.html#plain) or a [`remap`](https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/lumiscan-calibration/streams.html#remap) step. One step is handled for now; a list with more is malformed. Left out, or empty: a plain stream with 2 numbers per point. |
| `onExit` | No | Reserved for steps applied to the points before they are published. Not read yet: the module logs a warning, and the steps are not applied. |

- Adding, changing or removing the `stream` section takes effect with a `reset` of the module. No restart of the application is needed.
- A reset that changes how the source is read - a step of `onEntry` - restarts the stream on the module’s next cycle, about 100 ms later. A reset that changes only `enable`, `address`, `tag`, `queueSize` or `keepLatestOutput` restarts nothing: the running stream follows.
- The section also holds stream mode and the source as set at run time: `control/subscribe/execute` and `control/unsubscribe/execute` save them into it. See [Kept in the module configuration file](https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/lumiscan-calibration/streams.html#kept).
- A malformed `stream` section is a malformed module file: the module reports status `-2` (`invalidSetting`) and transforms nothing until it is corrected and reset. Malformed are, for example, stream mode without a source (`enable` set to `true` and no `address`), a step of another `kind`, and a key of a step - `kind`, `node`, `components`, `schema`, `rootType`, `array`, `x`, `y` or `filters` - written at the top of the section instead of in `onEntry`. The log names the key.

An older `subscriptions` key, which named several sources by tag, is not read any more: the module logs a warning that says so. Move its one source to `address` - its folder - and the step’s `node`.

To see what a source may hold, read `hdvisionsystems/lumiscan-calibration/system/meta/subscription-schema`: see [What a source may hold](https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/lumiscan-calibration/streams.html#subscription-schema).

### Plain: arrays of points {#plain}

```json
"stream": {
    "enable": true,
    "address": "plc/app/Application/sym/GVL_Vision",
    "onEntry": [
        { "kind": "plain", "node": "aPixelPoints", "components": 3 }
    ]
}
```

A stream without a step - no `onEntry`, or an empty one - is plain, with 2 numbers per point, and reads the node `points`: another Calibration module’s points (see [Chaining modules](https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/lumiscan-calibration/streams.html#chaining)). A `plain` step is needed for another node, such as a PLC array, or for 3 numbers per point.

| Key of the step | Required | Meaning |
| --- | --- | --- |
| `kind` | Yes | `"plain"` |
| `node` | No | The node of the folder that holds the array, for example a PLC symbol, `aPixelPoints`. `points` by default. |
| `components` | No | The numbers per point: `2` for `x,y` (the default), `3` for `x,y,z`. The lookup table maps a pixel, so a `z` is ignored. An array whose length is not a whole number of points is not transformed and is counted in `statistics/failed-updates`. |

### Remap: points from another application’s result {#remap}

```json
"stream": {
    "address": "hdvisionsystems/lumiscan-ai-object-matching/<module name>/control/subscribe/output/stream",
    "onEntry": [
        {
            "kind": "remap",
            "node": "result",
            "array": "instances",
            "x": "oriented_bounding_box.center_x",
            "y": "oriented_bounding_box.center_y",
            "filters": [
                { "field": "class_index", "anyOf": [0, 2] },
                { "field": "score", "min": 0.5 }
            ]
        }
    ]
}
```

This example transforms the centre of each box AI Object Matching finds on its image stream, for the classes `0` and `2` with a score of at least `0.5`. It reads the node `result` of the AI module’s stream folder, a flatbuffer of the default schema, `stream_detections`.

A stream result such as this one holds two things: its `lineage`, and the result itself - the same result the application writes to its regular output. The step reads inside the result, so `array` is the path as on the regular output: `instances`, AI Object Matching’s list of what it found. The points the module publishes carry the lineage of the AI result - the camera image it was inferred on - with the module’s own step added.

The example module the application ships, `example`, has such a step without filters. It reads AI Object Matching’s example module, also `example`, from its start. See [Module Configuration File](https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/lumiscan-calibration/module-configuration-file.html).

| Key of the step | Required | Meaning |
| --- | --- | --- |
| `kind` | Yes | `"remap"` |
| `node` | No | The node of the folder that holds the flatbuffer. `result` by default: the stream result of a LumiScan application, in its `control/subscribe/output/stream` folder. |
| `schema` | No | Which flatbuffer the node holds; `stream_detections`, AI Object Matching’s stream result, by default. Either the name of a schema the application ships, or the path of a compiled schema (`.bfbs`) file, relative to the module configuration file. The schemas shipped, with the `array` of each:<br><br>\* the stream results (node `result`): `stream_detections` (AI Object Matching, `instances`), `stream_template_matches` (Template Finder, `matches`), `stream_object_matches` (Object Finder, `matches`), `stream_areas` (Area Detector, `blobs`), `stream_codes` (the code readers, `results`), `stream_texts` (Text Reader, `words`); \* the regular outputs: `object_detection` (AI Object Matching’s `output/result`, `instances`), `template_match_result`, `object_find_result`, `area_detect_result`, `code_detect_result` and `text_read_result`, with the same lists; \* another Calibration module’s points: `stream_points` (node `points`, `array` `points`, `x` and `y` named `x` and `y`). |
| `rootType` | No | The table at the root of the buffer, with its namespace, for example `hdv.object_detection2d.Result`. Leave it out to use the schema’s own root type. |
| `array` | No | The path to the list whose elements are the points, for example `instances`. In a stream result it starts inside the result, as on the regular output. Left out: no list - the result itself is the one element, and each update gives one point, or none when a filter rejects it. See [One point per update](https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/lumiscan-calibration/streams.html#one-point). |
| `x`, `y` | Yes | The path within one element to its `x` and its `y`, for example `oriented_bounding_box.center_x`. |
| `filters` | No | Only the elements every filter passes become points. Each filter has a `field` (a path within an element to a number) and at least one of `anyOf` (a list of values the field must equal one of), `min` and `max` (inclusive bounds). An integer field is compared as an integer. |

A path is a list of field names joined with `.`, as the schema names them. Each step but the last must lead to a structure, and the last to a number. The module checks every path against the schema when the stream starts. If one does not fit, the stream does not start, and the log says which step is wrong. Two mistakes are named with the fix:

- an `array` that starts with the stream result’s own field, `result.instances`: the result is read already, write `"array": "instances"`;
- no `array` while `x` or `y` is only found in the elements of a list of the result: name the list, for example `"array": "instances"`.

#### One point per update {#one-point}

A result that is not a list - one pose, one position - gives one point per update. Leave `array` out, and name the fields within the result:

```json
{ "kind": "remap", "schema": "my_result.bfbs", "node": "result", "x": "pose.x", "y": "pose.y" }
```

The filters apply to that one element: an update it does not pass is published with no points.

Good to know:

- A field the element does not set reads as its default value in the schema, as for any flatbuffer reader.
- If a structure on a path is missing from an element, the point is published as `NaN,NaN,NaN`, and a filter on that path rejects the element.
- An update that is not a valid buffer of the given type is not transformed. It is counted in `statistics/failed-updates`, and the first one is written to the log.

## Addresses {#addresses}

All addresses below start with `hdvisionsystems/lumiscan-calibration/<module name>/`. Every module has them. The stream follows the layout of an execute method: `control/subscribe` owns its inputs and outputs.

**Table 1. Methods**

| Address | Meaning |
| --- | --- |
| `control/subscribe/execute` | Checks all of `control/subscribe/input/…` together, saves them in the module configuration file, then applies them: the stream follows on the module’s next cycle, with no restart. See [Subscribing at run time](https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/lumiscan-calibration/streams.html#subscribing). |
| `control/unsubscribe/execute` | Drops the source named by `control/unsubscribe/input/address`, which ends stream mode too, and saves that. |

**Table 2. Inputs**

| Address | Type | At start | Meaning |
| --- | --- | --- | --- |
| `control/subscribe/input/enable` | bool | `stream.enable`, or `false` | `true` runs the stream; `false` stops it. |
| `control/subscribe/input/address` | string | `stream.address`, or empty | The folder of the node to subscribe to, exactly as written. The step’s `node` names the node in it. |
| `control/subscribe/input/tag` | string | `stream.tag`, or empty | The tag on the points the module publishes, in their lineage. Empty: the module name. |
| `control/subscribe/input/queue-size` | uint32 | `stream.queueSize`, or 64 | How many updates may wait to be transformed, 1 to 4096. See [The queue](https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/lumiscan-calibration/streams.html#queue). |
| `control/subscribe/input/keep-latest-output` | bool | `stream.keepLatestOutput`, or `false` | `true` also writes each update’s points to the regular output. See [Keeping the latest output](https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/lumiscan-calibration/streams.html#keep-latest-output). |
| `control/unsubscribe/input/address` | string | empty | The source `control/unsubscribe/execute` drops: the address on `setting/stream/address`. |

Writing an input changes nothing by itself: only `control/subscribe/execute` applies the inputs. They start as what the module applies, and a reset sets them to the file’s values again, so a client can change one input and call the method.

**Table 3. Outputs**

| Address | Type | Meaning |
| --- | --- | --- |
| `control/subscribe/output/stream/active` | bool | `true` while the stream runs. |
| `control/subscribe/output/stream/points` | flatbuffers (`stream_points`) | The points of each update, transformed, with their lineage. Subscribe to it to receive each one. A read returns the latest. See [The points](https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/lumiscan-calibration/streams.html#points). |
| `control/subscribe/output/stream/plain-points` | float32 array | The same points as a plain array, `x0,y0,z0,x1,y1,z1,…`, without the lineage: for a client that cannot read a flatbuffer, such as a PLC. |
| `control/subscribe/output/stream/statistics/…` | uint64 | Counters of the current or last stream, see [Reading the statistics](https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/lumiscan-calibration/streams.html#statistics). |

**Table 4. Setting**

| Address | Type | Meaning |
| --- | --- | --- |
| `setting/stream/enable`, `setting/stream/address`, `setting/stream/tag`, `setting/stream/queue-size`, `setting/stream/keep-latest-output` | as the inputs | What the module applies now, as saved in the `stream` section. |
| `setting/settings-hash` | string | The hash of what the points are transformed with, as 16 hex digits. See [The settings hash](https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/lumiscan-calibration/streams.html#settings-hash). |

Unless `keep-latest-output` is set, the points of the stream are published only on `control/subscribe/output/stream/points` and `control/subscribe/output/stream/plain-points`, and the regular outputs keep the result of the last transform on request.

### What a source may hold {#subscription-schema}

`hdvisionsystems/lumiscan-calibration/system/meta/subscription-schema` (string, read only, experimental) describes what the node a module subscribes to may hold, as a JSON Schema (draft-04) of the node’s JSON form. It lists three kinds, any one of which fits (`anyOf`):

- a plain array of numbers - a `plain` step, or none;
- a `stream_points` - another Calibration module’s points, read plain;
- a `stream_detections` - AI Object Matching’s stream result, read by a `remap` step with the default schema.

It is the same for every module, so it does not say which kind one module reads: its `onEntry` step says that. The descriptions in it come from the flatbuffer schemas. A field of a flatbuffer is shown as the JSON of `flatc --strict-json` renders it: an enum by its name, a structure as an object.

## Running a stream {#running}

1. Subscribe to `control/subscribe/output/stream/points`, or to `control/subscribe/output/stream/plain-points` for the plain array.
2. Write `true` to `control/subscribe/input/enable` - and the source’s address, if the module has none yet - and `true` to `control/subscribe/execute`. Wait until `control/subscribe/output/stream/active` is `true`. Updates of the source are transformed from then on.
3. To stop, write `false` to `control/subscribe/input/enable` and `true` to `control/subscribe/execute`.

Good to know:

- Stream mode is saved in the `stream` section before it applies: after a restart of the application the module streams again, or not, as it did before. Nobody has to call the method again.
- The stream runs only while the licence is present.
- If the stream cannot start because a remap path does not fit the schema, `control/subscribe/output/stream/active` stays `false` and the reason is written to the log. It is not retried until the module is reset, or stream mode is switched off and on again with `control/subscribe/execute`.
- A source that cannot be subscribed to, for example a node that does not exist yet, does not keep the stream from running: it is tried again every 5 seconds, and the first failure is written to the log.
- Transforming on request keeps working while the stream runs: the `transform` handshake and `control/transform/execute` are never refused because of the stream.
- A `reset` replaces the lookup table at once, also for the running stream: the next update is transformed with the new table. If the reset fails, the module has no table, and the stream publishes `NaN` for every point until a reset succeeds.

## The queue {#queue}

The updates of the source wait in a queue, in the order they arrive, and are transformed one after the other. An update is dropped only when the queue is full - `queueSize` updates, 64 by default, are already waiting: then the oldest goes, and is counted in `statistics/skipped-updates`.

A larger `queueSize` rides out longer bursts without dropping an update, but when the source updates faster than the module transforms for longer, the points it publishes are older: up to `queueSize` updates behind. A smaller one keeps the points recent and drops more.

A changed queue size applies at once, with no restart of the stream. When it shrinks below the updates already waiting, the oldest of them are dropped and counted as skipped.

## Subscribing at run time {#subscribing}

A PLC or another client changes the source and stream mode while the application runs, with or without a running stream:

1. Write the inputs that change to `control/subscribe/input/…` - for another source, `control/subscribe/input/address`, its folder (the node in it stays the step’s); to start or stop, `control/subscribe/input/enable`; for another tag on the points, `control/subscribe/input/tag`.
2. Write `true` to `control/subscribe/execute`.

The method checks all inputs together, saves them in the `stream` section, then applies them: `setting/stream/…` shows them at once, and a running stream follows on the module’s next cycle. Another address replaces the source - no unsubscribe is needed first -, and the updates the old source had waiting are dropped and counted as skipped. The queue size and `keep-latest-output` apply without subscribing again, and so does the tag: the points published from then on carry it.

To drop the source, write its address to `control/unsubscribe/input/address` and `true` to `control/unsubscribe/execute`. That ends stream mode too, and saves `enable` as `false` with no address. The tag stays: it marks the module’s points, not the source. `control/subscribe/input/…` are set to that as well, so a later `control/subscribe/execute` that changes another input does not bring the source back. A `/` at either end of an address does not matter.

The methods answer as follows. Where a result has one name only, it is the name on the ctrlX Data Layer; LumiScan Keryx reports the same result under its own name, see [Results of a method call](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/status-codes.html#method-results).

| Result | When |
| --- | --- |
| `DL_OK` | Done. |
| `DL_INVALID_VALUE` (ctrlX Data Layer), `Rejected` (LumiScan Keryx) | `control/subscribe`: `enable` is `true` and the address is empty, or the queue size is not 1 to 4096. `control/unsubscribe`: the address is not the source, or there is no source. Nothing changed. |
| `DL_CREATION_FAILED` | The change could not be saved in the module configuration file: the file could not be read or written. Nothing changed: the stream stays as it was. The answer and the log say why. |
| `DL_RESOURCE_UNAVAILABLE` | The settings were edited on `system/settings` and the application waits for a restart. |

## Kept in the module configuration file {#kept}

Stream mode and the source are settings of the module, in the `stream` section of its configuration file. `control/subscribe/execute` and `control/unsubscribe/execute` save `enable`, `address`, `tag`, `queueSize` and `keepLatestOutput` there before they apply them: when they cannot be saved, the method answers `DL_CREATION_FAILED` and nothing changes. After a restart the module subscribes to the same source and, when `enable` is `true`, starts its stream at once.

Saving changes only those values: the rest of the file stays as it was, comments and the steps of `onEntry` included. A file without a `stream` section gets one, with those values and no step: a plain stream.

A reset reads the file again, and sets the inputs to it: a change you make in the file by hand takes effect with the next reset.

## Keeping the latest output {#keep-latest-output}

With `keep-latest-output` set, the points of each update are also written to the module’s regular output, as a transform on request writes them: `output/x-coordinate-array`, `output/y-coordinate-array` and `output/z-coordinate-array`, `output/timestamp`, and `output/package-identifier`, counted on from the transforms on request. A client that reads the regular output - a PLC program written for the `transform` function, for example - then sees the newest points of the stream there. A point that cannot be transformed is `NaN` there too.

It costs a copy of every update’s points, so it is off by default. The points on `control/subscribe/output/stream/points` are published first.

## The points {#points}

`control/subscribe/output/stream/points` holds a FlatBuffers table of type `stream_points`, registered on the Data Layer as `types/hdvisionsystems/lumiscan-calibration/stream_points`. Its compiled schema is installed as `bfbs/stream_points.bfbs`.

| Field | Meaning |
| --- | --- |
| `points` | One `x`, `y`, `z` (float32) per point of the update, in its order. |
| `invalid` | How many of the points could not be transformed. |
| `lineage` | Where the update came from, see [The lineage of the points](https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/lumiscan-calibration/streams.html#lineage). |

`control/subscribe/output/stream/plain-points` publishes the same points as `x0,y0,z0,x1,y1,z1,…`, right after `control/subscribe/output/stream/points`.

- The i-th point is the i-th point of the update. A point that cannot be transformed is published as `NaN` in its place, so the order is kept. A point cannot be transformed when it lies outside the lookup table, or when the module has no table.
- An update with no points is published with none.
- `z` is the lookup table’s value. A `z` in a plain source with `components` `3` is ignored.

> [!NOTE]
> A point outside the lookup table is published as `NaN` by the stream only. On request, the `transform` function returns a value from the edge of the table for such a point, without an error, as it always did. Keep the points you request within the image the table was made for.

### Chaining modules {#chaining}

A module’s `control/subscribe/output/stream/points` can be the source of a plain stream in another module. The second module reads it as `x,y,z` points, whatever its `components` say, transforms the `x` and `y` of each, and ignores the `z`. Its points carry the first module’s lineage with its own step added. `control/subscribe/output/stream/plain-points` works as a source too, with `components` `3`, but its points start a lineage of their own.

### The lineage of the points {#lineage}

`lineage.steps` lists where an update’s points came from, origin first:

- A source that carries a lineage - AI Object Matching’s `control/subscribe/output/stream/result`, another module’s `control/subscribe/output/stream/points` - passes its steps on: the camera’s step first (`producer` the camera’s address, `tag` the Cam Driver module’s tag, `run` and `sequence` the image’s place in the camera’s stream), then the AI module’s, with the AI module’s tag.
- A source that carries none - a PLC array - gets a step made for it, marked `synthesized`: its `producer` is the node’s address, the folder and the node; it has no `tag`; its `sequence` the module’s own count since the stream started. On LumiScan Keryx, the `sequence` is the Data Layer’s sequence number of the update where there is one, else the module’s own count.
- The module’s own step comes last: `producer` is the module’s address, `hdvisionsystems/lumiscan-calibration/<module name>`; `tag` the module’s tag (`stream.tag`), or the module name when it has none; `run` when the module’s stream started; `sequence` the update’s number in the run; `settings_hash`, see [The settings hash](https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/lumiscan-calibration/streams.html#settings-hash); `elapsed_us` the microseconds from the update’s arrival to the points' publication.

The `tag` of each step says which module processed the update there - the module’s own name, or the tag it was given. Give two modules of the same name in different applications, or a module whose name says little, a tag that says what it does on your line.

A source changed while the stream runs keeps the module’s run: the updates of the new source are numbered on, and the `producer` of their first step names it.

### The settings hash {#settings-hash}

`setting/settings-hash`, and the `settings_hash` of the module’s step, identify what the points are transformed with. The hash changes when one of these changes:

- the module configuration file’s settings - except the transform’s `name`; the stream’s `enable`, `address`, the `node` of its step, `tag`, `queueSize` and `keepLatestOutput`, which switch, choose, pace and mark the updates rather than change their points; and its `onExit`, which is not read yet;
- the lookup table (`relativePathToTiff`) by its content - a new table under the old file name is a new hash; and the `schema` of a remap step, by its content - the same schema under another name is the same hash;
- the application’s version.

A reset reads them again. The first time a hash appears, the module writes the settings it stands for to `settings-history/<module name>-<hash>.json` in the application’s configuration folder, so a hash found in the points' lineage can be looked up later.

> [!NOTE]
> The points carry the hash only. A different hash says that something they are transformed with changed, not what changed. To find out, compare the two files in `settings-history` that the hashes name, by hand.

## Reading the statistics {#statistics}

The counters start from zero each time the stream starts, and are updated about four times a second while it runs. All addresses start with `control/subscribe/output/stream/statistics/`.

| Counter | Meaning |
| --- | --- |
| `elapsed-ms` | Milliseconds since the stream started. Divide the other counters by it for rates. |
| `received-updates` | Updates of the source that arrived. |
| `transformed-updates` | Updates transformed and published on `control/subscribe/output/stream/points` and `control/subscribe/output/stream/plain-points`. |
| `skipped-updates` | Updates dropped unprocessed because the queue was full (`queueSize`, 64 by default): the module could not keep up with the source. The oldest waiting update is dropped first. Also the updates waiting when the source was replaced, or when the queue size shrank below them. |
| `failed-updates` | Updates that could not be transformed: not the expected type or length, or not a valid buffer. The first one is written to the log. |
| `lost-updates` | Updates dropped before they arrived. For a source that carries a lineage, counted from gaps in the `sequence` of its producer’s step within one run. On LumiScan Keryx, for a plain array, from gaps in the Data Layer’s sequence numbers. A new source starts the count again. |
| `points` | Points transformed, all updates together. |
| `invalid-points` | Of those, the points published as `NaN`. |
| `transform-us` | Microseconds all transforms took, summed. Divide by `transformed-updates` for the mean. |

## What a stream receives {#data-layers}

`control/subscribe/output/stream/points` publishes every update to its subscribers. What the stream itself receives depends on the source node:

| Data Layer | Source that publishes each update (for example AI Object Matching’s `control/subscribe/output/stream/result`, or another module’s `control/subscribe/output/stream/points`) | Ordinary node (for example a PLC array) |
| --- | --- | --- |
| ctrlX Data Layer (ctrlX OS) | Every update, in order. | The value about every 100 ms. Changes in between are not seen. |
| LumiScan Keryx (PC) | Every update, in order. | Every **change**: writing the same values again is not an update. |

On the ctrlX Data Layer, the stream has not yet been measured with a PLC source on a device.

The stream concept of all LumiScan applications is described in [Streams (Experimental)](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/streams.html).

# LumiScan Calibration Folder Structure

URL: https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/lumiscan-calibration/folder-structure.html

The settings of the application are files in its settings folder, **lumiscan-calibration**. It contains:

- **lumiscan-calibration.json**, the application settings. See [Application Settings File](https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/lumiscan-calibration/application-settings-file.html).
- **\<module name>.json** for each module, for example **example.json**. See [Module Configuration File](https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/lumiscan-calibration/module-configuration-file.html).
- **\<file name>.tiff**, the calibration data a module names, provided by HD Vision Systems. See [Tiff File](https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/lumiscan-calibration/tiff-file.html).
- **schemas**, which describe the settings files to the editor.

## On ctrlX OS: Editing with the Built-In Website {#edit-with-built-in-website}

1. Log in to the ctrlX OS website.

2. Go to **Home**.

3. Select **Manage app data**.

   ![ctrlX OS home screen with Manage app data](https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/_images/2a.png)

4. Click the three dots and select **File View**.

   ![Manage app data list view with File View menu](https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/_images/1a.png)

5. Open the folder **lumiscan-calibration**. It contains the files listed above.

6. Click a file name to open it in the JSON Settings window on the right.

   ![JSON Settings window](https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/_images/jsonsettings.png)

## On a PC {#edit-on-a-pc}

On a PC, the settings are ordinary files. On Windows, the settings folder is `%APP_RESOURCE_DIR%\etc\lumiscan-calibration`, or without `APP_RESOURCE_DIR` `C:\ProgramData\HD Vision Systems GmbH\LumiScan Vision Suite\lumiscan-calib\etc\lumiscan-calibration`. See also [Where the files are](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/keryx.html#files).

Open the files in any text editor, preferably one that checks JSON against the schemas in the `schemas` folder.

# Application Settings File – LumiScan Calibration

URL: https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/lumiscan-calibration/application-settings-file.html

The settings of the application are stored in **lumiscan-calibration.json**. If the settings folder has no such file, the application copies its example there at start, together with the example module.

- **On ctrlX OS:** The example TIFF file does not ship with the app. The example module reports status `-2` until you upload your own TIFF file and reset the module.
- **On a PC:** The example TIFF file ships with the installation, so the example module works out of the box.

```json
{
    "$schema": "schemas/lumiscan-calibration.schema.json",
    "meta": {
        "inputFileType": "LumiScan-CtrlX-Calibration",
        "inputFileVersion": "1.0.0",
        "targetMachine": "MachineName",
        "programName": "LumiScan-Calibration",
        "programVersion": "1.0.0"
    },
    "modules": [
        "example.json"
    ],
    "system": {
        "debug": false,
        "logLevel": "INFO",
        "storage": {
            "type": "Internal",
            "parameters": {
                "rootPath": "output"
            }
        }
    }
}
```

The parameters are described in [Table 4](https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/lumiscan-calibration/application-settings-file.html#table-4-application-settings). The file may contain comments (`//` and `/* */`).

**Table 1. Table 4: Application JSON Settings File Description**

| Parameter | Description |
| --- | --- |
| `meta` | Metadata of the file. It is for information only. |
| `meta.inputFileType` | The file type: `LumiScan-CtrlX-Calibration`. |
| `meta.inputFileVersion` | The version of the file format: `1.0.0`. |
| `meta.targetMachine` | The name of the machine the configuration is intended for. |
| `meta.programName` | The application that uses the file: `LumiScan-Calibration`. |
| `meta.programVersion` | The application version the configuration was made for. |
| `modules` | The module configuration files, relative to this file. Each one is a module, named after its file without `.json`. See [Module Configuration File](https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/lumiscan-calibration/module-configuration-file.html). |
| `system.logLevel` | The log level: `TRACE`, `DEBUG`, `INFO`, `WARN`, `ERROR`, `FATAL` or `OFF`. The default is `INFO`. |
| `system.debug`, `system.storage` | Shared with the other LumiScan applications. Not used by LumiScan Calibration. |

> [!NOTE]
> Restart LumiScan Calibration after changing this file, for example after adding a module.
>
> - If the file cannot be read, the application writes the reason to the log and stops.
> - A module whose file or TIFF file cannot be loaded is still served: it reports status `-2` (`invalidSetting`) until its files are corrected and the module is reset.
> - With no module listed, the application keeps running, and `hdvisionsystems/lumiscan-calibration/system/status-text` says so.

## Starting from an Example (PC) {#generate-settings}

On a PC, the Calibration writes an example of its settings into a folder of your choice, and ends without starting. For example, on Windows:

```shell
lumiscan-calib --generate-settings C:\work\calibration-settings
```

Without a folder (`-g` alone) it writes into the current folder. The example is the application settings file `lumiscan-calibration.json`, its example module file `example.json` with the lookup table `example.tiff` that module names, and the four schemas in the `schemas` folder that an editor uses to check them. Existing files are never overwritten: when one of them is in the folder already, nothing is written and the Calibration says which.

The Calibration then names the folder it reads its settings from, by default (Windows) `C:\ProgramData\HD Vision Systems GmbH\LumiScan Vision Suite\lumiscan-calib\etc\lumiscan-calibration`. Edit the example, copy it there, and start the Calibration.

## Complete reference {#complete-reference}

Every setting of this file as its JSON Schema `lumiscan-calibration.schema.json` defines it, generated for version 2.0.0:

| Setting | Type | Default | Allowed values | Description |
| --- | --- | --- | --- | --- |
| `meta` | object |   |   | **Required.** Meta information about the application and current setting. This is mainly for information purpose and not used by the application itself |
| `meta/inputFileType` | string |   | not empty | **Required.** |
| `meta/inputFileVersion` | string |   | not empty | **Required.** |
| `meta/targetMachine` | string |   | not empty | **Required.** |
| `meta/programName` | string |   | not empty | **Required.** |
| `meta/programVersion` | string |   | not empty | **Required.** |
| `modules` | string[] |   | at least 1 entry | **Required.** List of module setting files that will be loaded by the application |
| `system` | object |   |   |   |
| `system/debug` | boolean | `false` |   | Enable debug mode for the application. |
| `system/logLevel` | string | `INFO` | `TRACE`, `DEBUG`, `INFO`, `WARN`, `ERROR`, `FATAL` | Log level for the application. |
| `system/storage` | object |   |   | Configuration for storage. The storage is used to store the images when save function is called. |
| `system/storage/type` | string |   | `Samba` | **Required.** The storage is a Samba storage. |
| `system/storage/parameters` | object |   |   | Parameters for the storage. The parameters are different for each storage type. |
| `system/storage/parameters/ip` | string |   | not empty | **Required.** The IP address of the Samba server. |
| `system/storage/parameters/remotePath` | string |   | not empty | **Required.** |
| `system/storage/parameters/domain` | string |   | not empty | **Required.** |
| `system/storage/parameters/username` | string |   | not empty | **Required.** |
| `system/storage/parameters/password` | string |   | not empty | **Required.** |

## JSON Schemas {#json-schemas}

The application keeps the JSON Schemas of its settings files in its `schemas` folder; those copies always match the installed version. The schemas of LumiScan Calibration 2.0.0 can also be downloaded: [JSON Schemas of LumiScan Calibration 2.0.0](https://docs.hdvisionsystems.com/schemas/lumiscan-calibration/2.0.0/index.html).

To have an editor such as Visual Studio Code check a copy of a settings file that you edit on your PC, point its `$schema` entry at the published schema:

```json
{
  "$schema": "https://docs.hdvisionsystems.com/schemas/lumiscan-calibration/2.0.0/lumiscan-calibration.schema.json",
  ...
}
```

Leave the `$schema` entry of the files on the device as the application wrote it.

# Module Configuration File – LumiScan Calibration

URL: https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/lumiscan-calibration/module-configuration-file.html

Each module is configured in a file of its own, **\<module name>.json**. The name of the file without `.json`, in lower case, is the module’s name on the Data Layer: `hdvisionsystems/lumiscan-calibration/<module name>`. The application ships one example, **example.json**: the module `example`.

The configuration defines how 2D image coordinates are converted into 3D coordinates on the calibrated plane, and optionally a stream of points to convert.

```json
{
    "$schema": "schemas/lumiscan-calibration-module.schema.json",
    "meta": {
        "inputFileType": "LumiScan-CtrlX-Calibration-Module",
        "inputFileVersion": "1.0.0",
        "targetMachine": "MachineName",
        "programName": "LumiScan-Calibration",
        "programVersion": "1.0.0"
    },
    "transform": {
        "name": "PlanarProjectionExample",
        "type": "from2dTo3d",
        "subtype": "lookUpTable",
        "relativePathToTiff": "example.tiff",
        "interpolationMethod": "linear4Neighbors",
        "offsetX": 0.0,
        "offsetY": 0.0,
        "scaleX": 1.0,
        "scaleY": 1.0
    },
    "stream": {
        "address": "hdvisionsystems/lumiscan-ai-object-matching/example/control/subscribe/output/stream",
        "onEntry": [
            {
                "kind": "remap",
                "node": "result",
                "array": "instances",
                "x": "oriented_bounding_box.center_x",
                "y": "oriented_bounding_box.center_y"
            }
        ],
        "enable": true,
        "keepLatestOutput": true,
        "queueSize": 64
    }
}
```

The parameters are described in [Table 5](https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/lumiscan-calibration/module-configuration-file.html#table-5-module-settings). The file may contain comments (`//` and `/* */`).

The example’s `stream` section reads the results of LumiScan AI Object Matching’s example module, `example`, from the start: the node `result` of its stream folder, and in it the list `instances`. It transforms the centre of each box found on the image stream, and also writes the points to the regular output. The results of AI Object Matching are always read this way, with a `remap` step in `onEntry`. For a module that reads another source, change the section or remove it: without one, a module streams plain. See [Transforming a Stream](https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/lumiscan-calibration/streams.html).

**Table 1. Table 5: Module JSON Settings Description**

| Parameter | Description |
| --- | --- |
| `meta` | Metadata of the file. `inputFileType` and `inputFileVersion` are required. |
| `meta.inputFileType` | The file type. For a module configuration file, the value must be `LumiScan-CtrlX-Calibration-Module`. |
| `meta.inputFileVersion` | The version of the file format. Currently, only `1.0.0` is supported. |
| `meta.targetMachine` | Optional. The name of the machine the configuration is intended for. |
| `meta.programName` | Optional. The application that uses the file: `LumiScan-Calibration`. |
| `meta.programVersion` | Optional. The application version the configuration was made for. |
| `transform` | The coordinate transformation. |
| `transform.name` | The transformation’s name, as the log shows it. It does not change the module’s name on the Data Layer. |
| `transform.type` | The transformation type. Currently, only `"from2dTo3d"` is supported. |
| `transform.subtype` | The transformation subtype. Currently, only `"lookUpTable"` is supported. |
| `transform.relativePathToTiff` | The path of the TIFF file with the calibration data, relative to this file. See [Tiff File](https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/lumiscan-calibration/tiff-file.html). |
| `transform.interpolationMethod` | How a value between calibrated points is found: `"closestPixel"`, `"linear4Neighbors"` or `"bilateralInterpolation"`. |
| `transform.offsetX`, `transform.offsetY` | Offsets subtracted from the input coordinates before the table is looked up. The default is `0.0`. |
| `transform.scaleX`, `transform.scaleY` | Factors the input coordinates are scaled by, after the offset, before the table is looked up. The default is `1.0`. |
| `stream` | Optional, experimental. A stream of points to convert as they arrive: the source and stream mode, and in `onEntry` the step that reads each update. See [Configuring a stream](https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/lumiscan-calibration/streams.html#configuring). |

> [!NOTE]
> After changing the file, reset the module (`control/reset`): it reads the file and the TIFF file again, without a restart of the application. This applies to the `stream` section too. Only adding or removing a module needs a restart.
>
> If the file or its TIFF file cannot be loaded, the module is still served, but reports status `-2` (`invalidSetting`) and converts nothing until a reset succeeds.

## Complete reference {#complete-reference}

Every setting of this file as its JSON Schema `lumiscan-calibration-module.schema.json` defines it, generated for version 2.0.0:

| Setting | Type | Default | Allowed values | Description |
| --- | --- | --- | --- | --- |
| `meta` | object |   |   | **Required.** |
| `meta/inputFileType` | string |   | not empty | **Required.** |
| `meta/inputFileVersion` | string |   | not empty | **Required.** |
| `meta/targetMachine` | string |   | not empty | **Required.** |
| `meta/programName` | string |   | not empty | **Required.** |
| `meta/programVersion` | string |   | not empty | **Required.** |
| `transform` | object |   |   | **Required.** |
| `transform/name` | string |   | pattern `^[a-zA-Z0-9_-]+$` | **Required.** only [a-Z], [0-9], '-' and '\_' are allowed. Unique ID of the camera configuration. This is used to identify different camera on datalayer. |
| `transform/type` | string |   | `from2dTo3d` | **Required.** |
| `transform/subtype` | string |   | `lookUpTable` | **Required.** |
| `transform/relativePathToTiff` | string |   | not empty | **Required.** |
| `transform/interpolationMethod` | string |   | `linear4Neighbors`, `closestPixel` | **Required.** |
| `transform/offsetX` | number |   |   | **Required.** |
| `transform/offsetY` | number |   |   | **Required.** |
| `transform/scaleX` | number |   |   | **Required.** |
| `transform/scaleY` | number |   |   | **Required.** |

# TIFF File – LumiScan Calibration

URL: https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/lumiscan-calibration/tiff-file.html

The TIFF file contains calibration data used to convert 2D image coordinates into 3D coordinates on the calibrated plane. It is required for the LumiScan Calibration application and is provided by HD Vision Systems.

To obtain a TIFF file:

1. Contact HD Vision Systems to obtain a calibration plate.
2. Place the calibration plate on the plane you want to calibrate.
3. Capture at least one image of the calibration plate with the camera.
4. Send the captured images to HD Vision Systems.
5. HD Vision Systems will provide the corresponding TIFF file.

# Adding a New Module – LumiScan Calibration

URL: https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/lumiscan-calibration/adding-new-module.html

You can create a new module file by duplicating an existing one. A module can also be created and activated through the Data Layer, see [Adding and removing modules](https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/lumiscan-calibration/settings-on-the-data-layer.html#adding-and-removing-modules).

## On ctrlX OS {#adding-on-ctrlx-os}

1. Click the three dots to the right of the file name.

2. Select **Copy**. The copy file window opens.

   ![File actions menu with Copy option](https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/_images/rename.png)

   ![Copy file dialog](https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/_images/copyexample.png)

3. Enter a new file name. It becomes the module’s name on the Data Layer, without `.json` and in lower case.
   > [!NOTE]
   > You can also rename the file later: click the three dots to the right of the file name and select **Rename**.

4. Click **Copy** to confirm. The new module configuration file is created.

5. Edit the new file, for example to name its own TIFF file. See [Module Configuration File](https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/lumiscan-calibration/module-configuration-file.html).

6. Add the name of the new file to the application settings (`lumiscan-calibration.json`):

   a. Left-click `lumiscan-calibration.json`. The JSON settings window opens on the right.

      ![lumiscan-calibration.json JSON settings window](https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/_images/jsonsettings1.png)

   b. Add the file name to the `modules` list.

      ![modules field detail](https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/_images/jsonsettingsdet.png)

7. Restart LumiScan Calibration. The new module appears under `hdvisionsystems/lumiscan-calibration/<module name>`.

## On a PC {#adding-on-a-pc}

1. Copy an existing module file in the settings folder under a new name. The name becomes the module’s name on the Data Layer, without `.json` and in lower case.
2. Edit the new file, for example to name its own TIFF file. See [Module Configuration File](https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/lumiscan-calibration/module-configuration-file.html).
3. Add the name of the new file to the `modules` list of the application settings (`lumiscan-calibration.json`).
4. Restart LumiScan Calibration. The new module appears under `hdvisionsystems/lumiscan-calibration/<module name>`.

# Settings on the Data Layer – LumiScan Calibration

URL: https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/lumiscan-calibration/settings-on-the-data-layer.html

## Data Layer {#data-layer}

LumiScan Calibration offers its functions on the Data Layer under `hdvisionsystems/lumiscan-calibration`.

On ctrlX OS (ctrlX CORE or ctrlX IPC), LumiScan Calibration uses the [ctrlX Data Layer](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/ctrlx-data-layer.html).

On a PC with Windows 11 or Ubuntu 24.04, LumiScan Calibration uses [LumiScan Keryx](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/keryx.html).

The node addresses, types and call patterns are the same on both. LumiScan Calibration offers:

- [ready/request handshakes](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/handshake.html)
- [execute methods](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/execute.html)
- a [stream](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/streams.html) subscription to one source (experimental)

How addresses are built, how to call functions, the status codes and the tools are described in [LumiScan Keryx](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/index.html).

LumiScan Calibration shows the settings it was started with on the Data Layer, on `hdvisionsystems/lumiscan-calibration/system/settings`. You can read them there without access to the configuration folder, and change them there: the application checks a change, saves it to its settings files, and asks to be restarted. `hdvisionsystems/lumiscan-calibration/system/control/restart/execute` restarts it. The `system` node of all LumiScan applications is described in [Settings, Modules and Restart](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/settings-and-modules.html).

Where a result below has one name only, such as `DL_OK` or `DL_CREATION_FAILED`, it is the name on the ctrlX Data Layer; LumiScan Keryx reports the same result under its own name, see [Results of a method call](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/status-codes.html#method-results).

## What the node shows {#what-the-node-shows}

`settings` holds one JSON document, as text:

- the application settings file, `lumiscan-calibration.json`, as it was read;
- in its `modules` list, each module configuration file’s content instead of the file’s name. `"$file"` names the file each module came from;
- a module file that could not be read appears as `{"$file": ..., "$error": ...}`, where `"$error"` says why. That is also why the module did not start;
- every value named `password` shows as `"***"`.

For example:

```json
{
  "$schema": "schemas/lumiscan-calibration.schema.json",
  "meta": { ... },
  "modules": [
    {
      "$file": "example.json",
      "$schema": "schemas/lumiscan-calibration-module.schema.json",
      "transform": {
        "name": "PlanarProjectionExample",
        "relativePathToTiff": "example.tiff",
        ...
      }
    }
  ],
  "system": { ... }
}
```

Comments in the files are not shown.

The node shows the files as the application read them at start. A module’s reset reads its module file again, and the node then shows that file as it was read.

## Changing the settings {#changing-the-settings}

Read `settings`, change what you need, and write the whole document back. These rules apply:

- Each module keeps its `"$file"`. It must name one of the application’s module files: a module cannot be added here. To add one, see [Adding and removing modules](https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/lumiscan-calibration/settings-on-the-data-layer.html#adding-and-removing-modules).
- A module left out of `modules` is no longer listed in `lumiscan-calibration.json`. Its file stays where it is.
- `"***"` for a password keeps the password the file has. Any other value replaces it.
- A file whose content does not change is not written. A changed file is changed only where its content changed: comments and layout stay. A new key or list element goes after the last one there; a removed key goes with its line, a comment on that line included. Only an object that both gained and lost keys, or a list that lost an element, is written anew, without the comments inside it. The previous file is kept beside it as `<file>.bak`.
- A key such as `"_comment"` is content like any other, so it is shown and kept.

The application checks the change before anything is written: the application settings file has to load, and each changed module configuration file has to load its lookup table and its `stream` section, as a reset would. A lookup table that does not exist is refused. An edit the check refuses, or that is not valid JSON, is answered with `DL_INVALID_VALUE` (ctrlX Data Layer) or `Rejected` (LumiScan Keryx). The reason is in the log, and nothing is written.

An edit that writes nothing answers `DL_OK` and changes nothing.

### Restart required {#restart-required}

A change that was saved takes effect only with the next start. Until then the application runs with settings that are no longer those of its files, so it stops working:

- `hdvisionsystems/lumiscan-calibration/system/restart-required` is `true`;
- `hdvisionsystems/lumiscan-calibration/system/status-text` says which files changed;
- every module reports status `-5` (`restartRequired`). It answers no request, and its `ready` signals are `false`;
- every `execute` method of a module answers `DL_RESOURCE_UNAVAILABLE`. That includes `reset`, which would otherwise load part of the new settings;
- a running stream stops.

Only a restart ends this. A reset does not. The log has the message at error level.

Further changes are possible in the meantime. After a change, `settings` shows the files as saved, which is what the next start loads, not what the application runs with.

If a file could not be saved, the write answers `DL_CREATION_FAILED`. Files changed before it stay changed, so the application requires a restart all the same. Correct the files, then restart.

## Adding and removing modules {#adding-and-removing-modules}

Three methods of `hdvisionsystems/lumiscan-calibration/system` handle modules, each under `control/<method>/` as `control/restart` is. Each takes the module’s id, the name of its file without `.json`, in `control/<method>/input/module-id`:

| Method | What it does |
| --- | --- |
| `create-module` | Writes the module file `<module-id>.json` with the JSON in `control/create-module/input/content`. The application checks it as it checks a changed module file. The module is not active yet, so nothing has to be restarted. An existing file is not overwritten: change it through `settings`. |
| `activate-module` | Adds `<module-id>.json`, which has to exist, to the `modules` list, after the application has checked the module. It runs from the next start, so the application then requires a restart (see [Restart required](https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/lumiscan-calibration/settings-on-the-data-layer.html#restart-required)). |
| `deactivate-module` | Takes `<module-id>.json` off the `modules` list. The file stays, so `activate-module` can list it again. It stops with the next start, so the application then requires a restart. |

Each method reports on `control/<method>/output/status-code` and `control/<method>/output/status-text`:

| Code | Meaning |
| --- | --- |
| 1 | Done. |
| -2 | The input or the module was refused: `status-text` says why. Nothing was written. |
| -6 | A file could not be written. |
| -9 | `activate-module`: there is no such file. `deactivate-module`: the module is not active. |
| -10 | `create-module`: the file exists. `activate-module`: the module is active already. |

The method answers `DL_OK` when it is done, `DL_INVALID_VALUE` (ctrlX Data Layer) or `Rejected` (LumiScan Keryx) when it refused, and `DL_CREATION_FAILED` when a file could not be written. For example, to add the module `conveyor`:

1. Write the module’s JSON to `hdvisionsystems/lumiscan-calibration/system/control/create-module/input/content` and `conveyor` to `control/create-module/input/module-id`, then call `control/create-module/execute`.
2. Write `conveyor` to `control/activate-module/input/module-id`, then call `control/activate-module/execute`.
3. Call `hdvisionsystems/lumiscan-calibration/system/control/restart/execute`.

## Restarting the application {#restarting}

`hdvisionsystems/lumiscan-calibration/system/control/restart/execute` ends the application and starts it again. It reads its settings files anew, which also applies changes made to the files by hand, and ends `restart-required`.

- **On ctrlX OS:** the application ends, and ctrlX OS starts it again after about five seconds.
- **On a PC:** the application starts itself again once it has released everything it held. It uses the same program, arguments and working folder. It is a new process, in the same console, and its output goes where the first one’s went.

The method answers `DL_OK` as soon as the restart has begun. The application’s nodes then disappear until it is up again: wait until `hdvisionsystems/lumiscan-calibration/system/restart-required` can be read again.

> [!NOTE]
> A restart is not tied to a change. It also restarts an application whose settings did not change.

# Uploading Data – LumiScan Calibration

URL: https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/lumiscan-calibration/uploading-data.html

A TIFF calibration file is required to use LumiScan Calibration. Configuration files can optionally be uploaded or changed if you want to use custom application or module settings.

## On ctrlX OS {#uploading-on-ctrlx-os}

> [!NOTE]
> Most data can be uploaded directly through the ctrlX Web UI. Use WebDAV only when direct upload is not available or when you need to access the application folder structure.

![ctrlX Web UI data upload](https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/_images/ctrlx-web-ui-upload.png)

### Uploading with WebDAV

To upload files using WebDAV:

1. Go to the WinSCP website.

2. Download and install the latest version of WinSCP.

3. Start WinSCP.

4. On the login page, select **WebDAV** as the **File protocol**.

5. Select **TLS/SSL** for **Encryption**.

6. Enter your user name and password.

   ![WinSCP download page](https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/_images/WinSCP.png)

   ![WinSCP login window](https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/_images/dav1.png)

7. Navigate to `/solutions/webdav/appdata`.

8. The application folder structure is displayed in the right-hand panel.

9. Drag and drop the TIFF file and, if required, configuration files into the corresponding LumiScan Calibration application folder.

![WinSCP location pointing to solutions/webdav/appdata](https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/_images/dav3.png)

![WinSCP two-panel view of the appdata folder structure](https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/_images/dav2.png)

## On a PC {#uploading-on-a-pc}

On a PC these are ordinary files. Copy them into the folder the application reads its settings from. On Windows, that is:

- `%APP_RESOURCE_DIR%\etc\lumiscan-calibration`, when the environment variable `APP_RESOURCE_DIR` is set;
- otherwise `C:\ProgramData\HD Vision Systems GmbH\LumiScan Vision Suite\lumiscan-calib\etc\lumiscan-calibration`.

Restart LumiScan Calibration after changing a file.

# Troubleshooting – LumiScan Calibration

URL: https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/how-tos/troubleshooting.html

This page first lists the general checks that help with every problem. Start with them. Then find your symptom in the categories below: each problem lists its symptoms, possible causes, a diagnostic procedure and the resolution. The last section lists what to send to support.

## General checks {#general-checks}

### Configuration {#general-configuration}

LumiScan Calibration uses:

- an application configuration file (`lumiscan-calibration.json`) that references
- one or more module configuration files (`<module name>.json`), each naming a TIFF file.

The configuration files can be found under:

- **On ctrlX OS:** **Manage App Data > active > lumiscan-calibration**
- **On a PC (Windows):** `%APP_RESOURCE_DIR%\etc\lumiscan-calibration`, or without `APP_RESOURCE_DIR` `C:\ProgramData\HD Vision Systems GmbH\LumiScan Vision Suite\lumiscan-calib\etc\lumiscan-calibration`

Their content is also shown on the Data Layer, on `hdvisionsystems/lumiscan-calibration/system/settings`. A module file that could not be read appears there with an `"$error"` that says why. See [Settings on the Data Layer](https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/lumiscan-calibration/settings-on-the-data-layer.html).

Restart LumiScan Calibration after changing `lumiscan-calibration.json`. After changing a module configuration file or its TIFF file, a reset of the module (`control/reset`) is enough.

For more information about the configuration files, see [Application Settings File](https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/lumiscan-calibration/application-settings-file.html) and [Module Configuration File](https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/lumiscan-calibration/module-configuration-file.html).

### Status of the application and its modules {#general-status}

- `hdvisionsystems/lumiscan-calibration/system/found-modules` lists the modules the application serves. `hdvisionsystems/lumiscan-calibration/system/status-text` is `"Initialized"` once it serves its modules, or says why it serves none.
- `hdvisionsystems/lumiscan-calibration/<module name>/control/status/code` and `.../control/status/text` report the outcome of the last function. An error status stays until the next request. The meaning of each value is listed in [Status Code Values](https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/lumiscan-calibration/functionalities.html#status-code-values).
- Status `-5` (`restartRequired`) means that the settings were changed on the Data Layer: restart the application with `hdvisionsystems/lumiscan-calibration/system/control/restart/execute`. See [Settings on the Data Layer](https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/lumiscan-calibration/settings-on-the-data-layer.html#restart-required).

### Logs {#general-logs}

If an issue cannot be resolved using the checks described below, review the log. Each module writes why it could not load its files or start its stream.

- **ctrlX OS:** the ctrlX OS system log. Read it in the Logbook of the ctrlX web interface, or with `journalctl`. See [ctrlX Data Layer on ctrlX OS](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/ctrlx-data-layer.html).
- **PC:** the output of LumiScan Calibration in its console.

### Data Layer {#general-data-layer}

For problems with the Data Layer itself, see [Data Layer troubleshooting](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/troubleshooting.html).

## Modules and addresses {#modules-and-addresses}

### Problem: A calibration module does not appear in the Data Layer {#faq-module-not-in-data-layer}

**Symptoms**

- There is no node `hdvisionsystems/lumiscan-calibration/<module name>` for a module you configured, and `hdvisionsystems/lumiscan-calibration/system/found-modules` does not list it.
- No module appears at all, or the application itself is missing from the Data Layer.

**Possible causes**

- The module configuration file is not listed under `modules` in `lumiscan-calibration.json`. A listed module appears even when its file cannot be loaded.
- The module is looked for under the wrong name. Its name is the name of its file without `.json`, in lower case. The `name` in the module’s `transform` block does not change it.
- `lumiscan-calibration.json` was changed, but the application was not restarted.
- `lumiscan-calibration.json` lists no module.
- The application stopped at start, for example because `lumiscan-calibration.json` is not valid JSON, or (ctrlX OS) because the licence is missing.

**Diagnostic procedure**

1. Read `hdvisionsystems/lumiscan-calibration/system/found-modules` - expected: the module’s name.
2. Check `modules` in `lumiscan-calibration.json` - expected: the module configuration file is listed.
3. Look for the module under the name of its file without `.json`, in lower case.
4. Read `hdvisionsystems/lumiscan-calibration/system/status-text` - expected: `"Initialized"`. Otherwise it says why the application serves no module, for example when `lumiscan-calibration.json` lists no module.
5. If the application itself is missing from the Data Layer, read the log (see [Logs](https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/how-tos/troubleshooting.html#general-logs)) - it says why the application stopped at start.

**Resolution**

- **If the file is not listed:** add the file name to the `modules` list of `lumiscan-calibration.json`, then restart LumiScan Calibration. See [Adding New Module](https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/lumiscan-calibration/adding-new-module.html).
- **If you looked under the wrong name:** use the name of the file without `.json`, in lower case: `hdvisionsystems/lumiscan-calibration/<module name>`.
- **If `lumiscan-calibration.json` was changed without a restart:** restart LumiScan Calibration, for example with `hdvisionsystems/lumiscan-calibration/system/control/restart/execute`.
- **If the application stopped at start:** correct `lumiscan-calibration.json` as the log says, then start the application again. If the log names a missing licence, see [Requirements](https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/lumiscan-calibration/requirements.html#licence).

**If the problem persists**

Send the information listed under [Information for support](https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/how-tos/troubleshooting.html#support-information) to support, together with the content of `system/status-text` and `system/found-modules`, and `lumiscan-calibration.json`.

### Problem: Data Layer addresses under lumiscan-cam-calibration no longer work {#faq-data-layer-name}

**Symptoms**

Addresses that start with `hdvisionsystems/lumiscan-cam-calibration/…` no longer work.

**Possible causes**

- From v1.2.1, the application’s Data Layer name changed from `lumiscan-cam-calibration` to `lumiscan-calibration`.

**Diagnostic procedure**

1. Check the version of LumiScan Calibration - the change applies to v1.2.1 and later.
2. Check the addresses your program or PLC uses - expected: they start with `hdvisionsystems/lumiscan-calibration/`.

**Resolution**

- **If the addresses still use the old name:** update all addresses to `hdvisionsystems/lumiscan-calibration/…`. See [Release Notes: v1.2.1](https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/release-notes/v1-2-1-2025-07-01.html).

**If the problem persists**

Send the information listed under [Information for support](https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/how-tos/troubleshooting.html#support-information) to support, together with the addresses that do not work.

## Transforming points {#transforming-points}

### Problem: `transform/ready` stays `false`, and the status is -2 {#faq-transform-not-ready}

**Symptoms**

- `control/transform/ready` stays `false`.
- `control/status/code` is `-2` (`invalidSetting`).
- `control/transform/execute` answers `DL_INVALID_OPERATION_MODE`.
- A running stream publishes `NaN` for every point.

**Possible causes**

- The module has no lookup table: its module configuration file or the TIFF file it names could not be loaded, for example because the TIFF file is missing.
- The module configuration file has invalid or missing parameters, including its `stream` section. A malformed `stream` section is a malformed module file, for example stream mode without a source (`enable` set to `true` and no `address`), a step of another `kind`, or a key of a step written at the top of the section instead of in `onEntry`.
- The licence is not available. The status is then `-4` (`missingLicense`), and the module runs no function until the licence is back.

**Diagnostic procedure**

1. Read `control/status/code` - `-2`: a file could not be loaded; `-4`: the licence is missing.
2. Read the log (see [Logs](https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/how-tos/troubleshooting.html#general-logs)) - it says why the files could not be loaded, and names a malformed key.
3. Check that the TIFF file named by `relativePathToTiff` exists beside the module configuration file.
4. Check the module configuration file for invalid or missing parameters, including its `stream` section.

**Resolution**

- **If a file could not be loaded (status `-2`):** correct the files and reset the module. The module does not keep transforming with the old table, so that a corrected file is never mixed with an outdated one. See [Reloading the settings](https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/lumiscan-calibration/functionalities.html#reset).
  1. Correct the module configuration file or the TIFF file.
  2. Reset the module (`control/reset`). No restart is needed.
  3. Check that `control/status/code` is `0` and `control/transform/ready` is `true`.
- **If the licence is missing (status `-4`):** install the licence `SWL-W-XCx-CALIBRATExHDVSx-V2NN`. On ctrlX OS, the application shuts down shortly after starting if the licence is missing. See [Requirements](https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/lumiscan-calibration/requirements.html#licence).

**If the problem persists**

Send the information listed under [Information for support](https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/how-tos/troubleshooting.html#support-information) to support, together with the module configuration file, the name of its TIFF file and the log lines of the failed load.

### Problem: The application does not react to a request {#faq-request-not-detected}

**Symptoms**

After you set `XXX/control/<function name>/request` to `true`, `XXX/control/<function name>/ready` does not change to `false`, or the function does not run. `XXX` is `hdvisionsystems/lumiscan-calibration/<module name>`.

**Possible causes**

- More than one process writes the `request` node. The behaviour is then undefined, because the application can miss a request.
- `request` was not set back to `false`. The module waits for `request` to fall for as long as it takes.
- Your program uses another Data Layer version than the application.

**Diagnostic procedure**

1. Check which programs write `XXX/control/<function name>/request` - expected: only one process.
2. After setting `request` to `true`, read `ready` - expected: `false` (the module has seen the request).
3. After setting `request` back to `false`, read `ready` - expected: `true` again when the function has finished.
4. Check the Data Layer version your program uses - expected: the same as the application.

**Resolution**

- **If more than one process writes `request`:** make sure only one process accesses `XXX/control/<function name>/request` at a time. A program that cannot coordinate with others can use the `execute` method instead (`XXX/control/<function name>/execute`), which refuses a second call while one runs.
- **If `request` was not set back:** set `request` to `false` after `ready` has changed to `false`. See [Running a function](https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/lumiscan-calibration/general-concept-of-handshake.html#functionality-execution).
- **If the Data Layer versions differ:** use the same Data Layer version as the application.

**If the problem persists**

Contact HD Vision Systems with the information listed under [Information for support](https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/how-tos/troubleshooting.html#support-information), together with the function you request and the values of `ready`, `request` and `control/status/code`.

### Problem: The transformed coordinates do not match the image {#faq-coordinates-wrong}

**Symptoms**

The transformed coordinates do not correspond to the expected positions.

**Possible causes**

- An axis is inverted.
- The required origin is not defined correctly. The calibration does not define the application-specific reference point automatically.
- Units are mixed, such as millimeters and pixels, in the application and connected systems.
- The configured TIFF file does not belong to the camera and calibrated plane in use.
- A point lies outside the lookup table. It gives a value from the edge of the table, without an error.

**Diagnostic procedure**

1. Move an object in a known direction and observe how the coordinates change - expected: each coordinate changes in the expected direction.
2. Check the reference point - expected: the origin your application needs is defined.
3. Check the units of the application and connected systems - expected: the same units throughout.
4. Check `relativePathToTiff` in the module configuration file - expected: the TIFF file for the camera and calibrated plane in use.
5. Check the input points - expected: within the image the lookup table was made for.

**Resolution**

- **If an axis is inverted:** a coordinate changes in the opposite direction. Send the observed and the expected direction to support (see [Information for support](https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/how-tos/troubleshooting.html#support-information)).
- **If the reference point is not defined:** define the origin your application needs. The calibration does not do this automatically.
- **If units are mixed:** use consistent units throughout the application and connected systems.
- **If the wrong TIFF file is configured:** configure the TIFF file for the camera and calibrated plane in use, then reset the module (`control/reset`).
- **If points lie outside the lookup table:** keep the points within the image the table was made for.

**If the problem persists**

Send the information listed under [Information for support](https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/how-tos/troubleshooting.html#support-information) to support, together with some input points, the coordinates you get and the coordinates you expect.

## Streams (experimental) {#streams-experimental}

### Problem: The stream does not start {#ts-stream-does-not-start}

**Symptoms**

`control/subscribe/output/stream/active` stays `false` after `control/subscribe/execute` was called with `control/subscribe/input/enable` set to `true`.

**Possible causes**

- `control/subscribe/input/address` is empty, or the queue size is not 1 to 4096: the call answers `DL_INVALID_VALUE` (ctrlX Data Layer) or `Rejected` (LumiScan Keryx).
- The module configuration file is malformed (status `-2`), for example a step of `stream.onEntry` the module does not have, or a key of a step written at the top of the `stream` section.
- A remap path does not fit the schema.
- The change could not be saved in the module configuration file: the call answers `DL_CREATION_FAILED`.
- The settings were edited on `system/settings`, and the application waits for a restart: the call answers `DL_RESOURCE_UNAVAILABLE`.
- The licence is missing. The stream runs only while the licence is present.

**Diagnostic procedure**

1. Check the answer of `control/subscribe/execute` - expected: `DL_OK`.
2. Check `control/status/code` - `-2`: the module configuration file is malformed; the log names the key.
3. Check `setting/stream/enable` and `setting/stream/address` - they show what the module applies.
4. Read the log (see [Logs](https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/how-tos/troubleshooting.html#general-logs)) - the module writes why the stream could not start, for example a remap path that does not fit the schema.

**Resolution**

- **If the address is empty or the queue size is out of range:** write the source’s folder to `control/subscribe/input/address`, or a queue size from 1 to 4096 to `control/subscribe/input/queue-size`, and call `control/subscribe/execute` again.
- **If the `stream` section is malformed or a remap path does not fit:** correct the `stream` section and reset the module. A failed start is retried after the reset, or after stream mode is switched off and on again with `control/subscribe/execute`. See [Configuring a stream](https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/lumiscan-calibration/streams.html#configuring).
- **If the call answers `DL_CREATION_FAILED`:** the module configuration file could not be read or written. The answer and the log say why. Nothing changed.
- **If the call answers `DL_RESOURCE_UNAVAILABLE`:** restart the application, see [Status of the application and its modules](https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/how-tos/troubleshooting.html#general-status).
- **If the licence is missing:** see [Requirements](https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/lumiscan-calibration/requirements.html#licence).

A source the stream cannot subscribe to does not keep it from starting: it is tried again every 5 seconds, and the first failure is in the log. See [Problem: The stream runs, but no points arrive](https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/how-tos/troubleshooting.html#ts-stream-no-points).

**If the problem persists**

Send the information listed under [Information for support](https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/how-tos/troubleshooting.html#support-information) to support, together with the answer of `control/subscribe/execute`, the values of `setting/stream/enable` and `setting/stream/address`, and the `stream` section of the module configuration file.

### Problem: The stream runs, but no points arrive {#ts-stream-no-points}

**Symptoms**

`control/subscribe/output/stream/active` is `true`, but no points, or invalid points, arrive on `control/subscribe/output/stream/points` or `control/subscribe/output/stream/plain-points`.

**Possible causes**

- `received-updates` stays `0`: the source does not change, or `setting/stream/address` and the step’s `node` name another node than intended.
- `failed-updates` grows: the updates are not of the expected kind.
- `invalid-points` grows with `points`: the points lie outside the lookup table, or the module has no table (status `-2`).
- `skipped-updates` grows: the source updates faster than the module transforms.

**Diagnostic procedure**

1. Check the counters under `control/subscribe/output/stream/statistics` - expected: `received-updates` grows, and `failed-updates`, `invalid-points` and `skipped-updates` stay at `0`.
2. Compare `setting/stream/address` and the step’s `node` with the node you intend - expected: the node `node` in the folder `address`, exactly as written, including the case.
3. Read the log (see [Logs](https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/how-tos/troubleshooting.html#general-logs)) - it warns about an address that names the node twice, says when the source could not be subscribed to, and shows the first failed update.

**Resolution**

- **If `received-updates` stays `0`:** make the source change, or correct `address` and `node`. The module subscribes to the node `node` in the folder `address`, exactly as written, including the case. An address that still ends in the node names it twice. On the ctrlX Data Layer, an ordinary node such as a PLC array is read about every 100 ms, and changes in between are not seen; on LumiScan Keryx, writing the same values again is not an update. See [What a stream receives](https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/lumiscan-calibration/streams.html#data-layers).
- **If `failed-updates` grows:** send updates of the expected kind. A plain stream needs a float32 or float64 array with a whole number of points; a remap stream needs a flatbuffer of the type its `schema` names.
- **If `invalid-points` grows:** keep the points within the lookup table, or, if the status is `-2`, follow [Problem: `transform/ready` stays `false`, and the status is -2](https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/how-tos/troubleshooting.html#faq-transform-not-ready).
- **If `skipped-updates` grows:** reduce the source’s rate or the number of points per update. For short bursts, a larger queue size (`control/subscribe/input/queue-size`, saved as `queueSize`) helps. See [The queue](https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/lumiscan-calibration/streams.html#queue).

**If the problem persists**

Send the information listed under [Information for support](https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/how-tos/troubleshooting.html#support-information) to support, together with the values of the counters under `control/subscribe/output/stream/statistics` and the `stream` section of the module configuration file.

## Information for support {#support-information}

If a problem persists, send the following to HD Vision Systems customer success at [customer.success@hdvisionsystems.com](mailto:customer.success@hdvisionsystems.com) or +49 6221 6721905. For licences, contact [licenses@hdvisionsystems.com](mailto:licenses@hdvisionsystems.com).

- The version of LumiScan Calibration.
- The platform: ctrlX OS and its version on a ctrlX CORE or ctrlX IPC, or a PC with Windows 11 or Ubuntu 24.04 and LumiScan Keryx.
- The log: on ctrlX OS, the ctrlX OS system log (Logbook of the ctrlX web interface, or `journalctl`); on a PC, the console output of LumiScan Calibration.
- The date and time when the error occurred.
- The Data Layer status: `system/status-text`, `system/found-modules`, and for the affected module `control/status/code`, `control/status/text` and the result that an `execute` call answered.
- The configuration: `lumiscan-calibration.json` and the module configuration files, or the content of `hdvisionsystems/lumiscan-calibration/system/settings`, and the name of the TIFF file.

# FAQ – LumiScan Calibration

URL: https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/faq.html

Short answers to common questions about LumiScan Calibration. Each entry links to the page with the details. Problems and error messages are described in [Troubleshooting](https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/how-tos/troubleshooting.html).

> [!TIP]
> Each entry has a fixed anchor (for example `#faq-status-codes`). To find an error message, search the [Troubleshooting](https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/how-tos/troubleshooting.html) page for it.

## Getting started

### What does LumiScan Calibration do? {#faq-what-does-calibration-do}

- **Answer:** It converts 2D image coordinates into the corresponding 3D coordinates on a calibrated plane, for example for robotic bin picking or object placement. The conversion uses calibration data from a TIFF file. The application runs on ctrlX OS (ctrlX CORE or ctrlX IPC) and on a PC with Windows 11 or Ubuntu 24.04. It is configured with JSON settings files, and is controlled through the Data Layer (inputs, outputs and status): the ctrlX Data Layer on ctrlX OS, LumiScan Keryx on a PC. From v2.1.0 a module can also transform a stream of points as they arrive (experimental).
- **More:** [Description](https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/lumiscan-calibration/description.html), [Requirements](https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/lumiscan-calibration/requirements.html)

### How do I get the TIFF calibration file? {#faq-get-tiff-file}

- **Answer:** The TIFF file is generated from calibration images and provided by HD Vision Systems:
  - Contact HD Vision Systems to obtain a calibration plate.
  - Place the plate on the plane you want to calibrate.
  - Capture at least one image of the plate with the camera.
  - Send the images to HD Vision Systems; you receive the corresponding TIFF file.
- **More:** [TIFF File](https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/lumiscan-calibration/tiff-file.html)

### How do I upload the TIFF file and configuration files? {#faq-upload-files}

- **Answer:** On ctrlX OS, most data can be uploaded directly through the ctrlX Web UI. Alternatively use WebDAV, for example with WinSCP: select **WebDAV** as **File protocol** and **TLS/SSL** as **Encryption**, log in, navigate to `/solutions/webdav/appdata` and drag the files into the LumiScan Calibration application folder. On a PC, the files are ordinary files: copy them into the application’s settings folder (on Windows `%APP_RESOURCE_DIR%\etc\lumiscan-calibration`, or without `APP_RESOURCE_DIR` `C:\ProgramData\HD Vision Systems GmbH\LumiScan Vision Suite\lumiscan-calib\etc\lumiscan-calibration`). The TIFF file is required; configuration files are optional.
- **More:** [Uploading Data](https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/lumiscan-calibration/uploading-data.html)

## Configuration

### Where are the configuration files and how are they structured? {#faq-config-files}

- **Answer:** On ctrlX OS, open **Home** > **Manage app data** in the ctrlX OS web interface, select **File View** and open the `lumiscan-calibration` folder. On a PC, they are in the settings folder `lumiscan-calibration` (on Windows under `%APP_RESOURCE_DIR%\etc`, or without `APP_RESOURCE_DIR` under `C:\ProgramData\HD Vision Systems GmbH\LumiScan Vision Suite\lumiscan-calib\etc`). The folder contains:
  - `lumiscan-calibration.json`: application settings; `modules` lists the module configuration files to load.
  - `<module name>.json` (for example `example.json`): settings of one transformation module.
  - `<file name>.tiff`: calibration data provided by HD Vision Systems.
  - `schemas`: the schemas that describe the settings files to an editor. Restart LumiScan Calibration after changing `lumiscan-calibration.json`. After changing a module configuration file or its TIFF file, a reset of the module (`control/reset`) is enough. The settings can also be read and changed on the Data Layer, on `hdvisionsystems/lumiscan-calibration/system/settings`.
- **More:** [LumiScan Calibration Folder Structure](https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/lumiscan-calibration/folder-structure.html#edit-with-built-in-website), [Application Settings File](https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/lumiscan-calibration/application-settings-file.html), [Settings on the Data Layer](https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/lumiscan-calibration/settings-on-the-data-layer.html)

### How do I add a new transformation module? {#faq-add-module}

- **Answer:** Copy an existing module file under a new name (on ctrlX OS: three dots > **Copy**, enter a new file name and confirm with **Copy**; on a PC: copy the file in the settings folder). Then add the new file name to the `modules` list of `lumiscan-calibration.json` and restart the application. The name of the file without `.json`, in lower case, is the module’s name on the Data Layer: `hdvisionsystems/lumiscan-calibration/<module name>`. The `name` in the module’s `transform` block does not change it. Alternatively, create and activate the module through the Data Layer with `system/control/create-module/execute` and `system/control/activate-module/execute`, then restart with `system/control/restart/execute`.
- **More:** [Adding a New Module](https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/lumiscan-calibration/adding-new-module.html), [Adding and removing modules](https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/lumiscan-calibration/settings-on-the-data-layer.html#adding-and-removing-modules)

### Which transformation parameters can I set? {#faq-module-parameters}

- **Answer:** In the `transform` block of a module file:
  - `type`: only `from2dTo3d` is supported; `subtype`: `lookUpTable`.
  - `relativePathToTiff`: path to the TIFF calibration file, relative to the module file.
  - `interpolationMethod`: `closestPixel`, `linear4Neighbors` or `bilateralInterpolation`.
  - `offsetX`, `offsetY` (default `0.0`) and `scaleX`, `scaleY` (default `1.0`). An optional, experimental `stream` section configures a stream of points to transform.
- **More:** [Module Configuration File](https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/lumiscan-calibration/module-configuration-file.html#table-5-module-settings)

## Operation

### How do I convert a 2D image point into a 3D point? {#faq-convert-point}

- **Answer:** With `XXX` = `hdvisionsystems/lumiscan-calibration/<module name>`:
  - Check that `XXX/control/transform/ready` is `true`.
  - Set `XXX/input/x-coordinate` and `XXX/input/y-coordinate` to the pixel coordinates. To convert several points at once, also write `XXX/input/x-coordinate-array` and `XXX/input/y-coordinate-array`; leave them empty to convert one point only.
  - Set `XXX/control/transform/request` to `true`, wait until `ready` is `false`, then set `request` to `false`. Wait until `ready` is `true` again. Alternatively, write any value to `XXX/control/transform/execute`: the write returns when the transform has finished.
  - Check that `XXX/control/status/code` is `0` (`"ready"`) and read `XXX/output/x-coordinate`, `y-coordinate` and `z-coordinate` (and the output arrays).
- **More:** [Transforming points](https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/lumiscan-calibration/functionalities.html#transform), [Execute methods](https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/lumiscan-calibration/functionalities.html#execute)

### What do the status codes mean? {#faq-status-codes}

- **Answer:** `hdvisionsystems/lumiscan-calibration/<module name>/control/status/code` reports the outcome of the last function: `0` `"ready"` (last function successful), `1` `"settingUp"`, `2` `"running"`, `3` `"waitingForClient"`, `-1` `"undefinedError"`, `-2` `"invalidSetting"` (module configuration file or TIFF file could not be loaded), `-3` `"invalidInput"` (one or more input values are invalid), `-4` `"missingLicense"` (ctrlX OS: required licence not available), `-5` `"restartRequired"` (settings changed on the Data Layer: restart the application), `-10001` `"inputXYSizeNotEqual"` (the input arrays differ in length). An error status stays until the next request.
- **More:** [Status Code Values](https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/lumiscan-calibration/functionalities.html#status-code-values)

## Troubleshooting {#troubleshooting}

Problems and error messages are described step by step in [Troubleshooting](https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/how-tos/troubleshooting.html):

- [A calibration module does not appear in the Data Layer](https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/how-tos/troubleshooting.html#faq-module-not-in-data-layer)
- [Data Layer addresses under lumiscan-cam-calibration no longer work](https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/how-tos/troubleshooting.html#faq-data-layer-name)
- [`transform/ready` stays `false`, and the status is -2](https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/how-tos/troubleshooting.html#faq-transform-not-ready)
- [The application does not react to a request](https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/how-tos/troubleshooting.html#faq-request-not-detected)
- [The transformed coordinates do not match the image](https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/how-tos/troubleshooting.html#faq-coordinates-wrong)
- [The stream does not start](https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/how-tos/troubleshooting.html#ts-stream-does-not-start)
- [The stream runs, but no points arrive](https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/how-tos/troubleshooting.html#ts-stream-no-points)

## Licensing and support

### Which licence do I need, and what happens without one? {#faq-licence}

- **Answer:** The ctrlX licence for LumiScan Calibration is `SWL-W-XCx-CALIBRATExHDVSx-V2NN`. Bought in the ctrlX Store for ctrlX OS, it is a ctrlX licence and needs no LumiScan Key. On ctrlX OS, the application shuts down shortly after starting if the licence is missing; the reason is in the system log. A licence lost while the application runs is reported as status `-4` `"missingLicense"`, and the module runs no function until it is back. For a PC, see the licensing information on the Requirements page.
- **More:** [Requirements](https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/lumiscan-calibration/requirements.html#licence), [Licensing FAQ](https://docs.hdvisionsystems.com/en/lumiscan-licensing/1.0.4/faq.html)

### Where can I find more answers or get support? {#faq-support}

- **Answer:** See the site-wide [LumiScan FAQ](https://docs.hdvisionsystems.com/en/faq.html). Contact HD Vision Systems customer success at [customer.success@hdvisionsystems.com](mailto:customer.success@hdvisionsystems.com) or +49 6221 6721905; for licences, [licenses@hdvisionsystems.com](mailto:licenses@hdvisionsystems.com).
- **More:** [Licensing FAQ](https://docs.hdvisionsystems.com/en/lumiscan-licensing/1.0.4/faq.html), [Data Layer FAQ](https://docs.hdvisionsystems.com/en/lumiscan-keryx/1.0.0/faq.html)

# v2.1.0 - not yet released – LumiScan Calibration

URL: https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/release-notes/v2-1-0.html

**Added:**

- **Execute methods.** `control/transform/execute` and `control/reset/execute` run a transform or a reset with a single write, and return when it has finished. They answer `DL_TOO_MANY_OPERATIONS` while another transform or reset of the module runs, and `DL_INVALID_OPERATION_MODE` without a lookup table or a licence. See [Execute methods](https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/lumiscan-calibration/functionalities.html#execute).
- **Transforming a stream (experimental).** A module subscribes to one Data Layer node, its source, and transforms every update of it as it arrives: `address` in the `stream` section of its configuration file names the folder, and the step in the section’s `onEntry` list the node in it. The node holds either the points themselves (a float array, for example from a PLC), or another application’s result, such as the objects AI Object Matching finds on an image stream. The step says which: none, or `plain`, for an array; `remap` for a result, with the list in it (`array`) and each element’s `x` and `y` - or no list, for one point per update. A stream result is read inside its result, as on the application’s regular output. The other keys of the section are those of every LumiScan application’s stream. The points are published on `control/subscribe/output/stream/points` with their lineage - the camera image an AI result was inferred on, or the PLC node they came from - and as a plain `x0,y0,z0,x1,y1,z1,…` array on `control/subscribe/output/stream/plain-points`, with `NaN` for a point outside the lookup table. `setting/settings-hash` identifies the lookup table and settings they are transformed with, and the module’s `tag` - its name unless `stream.tag` gives another - marks them as its own. With `keep-latest-output`, each update’s points are also written to the regular outputs. Transforming on request keeps working while the stream runs. See [Transforming a Stream (Experimental)](https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/lumiscan-calibration/streams.html).
- **What a source may hold.** `hdvisionsystems/lumiscan-calibration/system/meta/subscription-schema` describes it as a JSON Schema: a plain array of numbers, a `stream_points` or a `stream_detections`. See [What a source may hold](https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/lumiscan-calibration/streams.html#subscription-schema).
- **Subscribing at run time.** `control/subscribe/execute` applies the inputs under `control/subscribe/input/…` - stream mode, the source, the queue size, `keep-latest-output` - while the application runs, with no restart; `control/unsubscribe/execute` drops the source. Every module has the stream nodes, so adding a `stream` section needs a reset only, and a module without one gets one when it subscribes. See [Subscribing at run time](https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/lumiscan-calibration/streams.html#subscribing).
- **Stream mode and the source kept in the module configuration file.** The methods save them in the `stream` section before they apply them: the module starts with both again after a restart. See [Kept in the module configuration file](https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/lumiscan-calibration/streams.html#kept).
- **Several modules at once.** Each module listed in the application settings is served on its own, so a module waiting for its client never holds up another.
- **Settings on the Data Layer.** `hdvisionsystems/lumiscan-calibration/system/settings` shows the settings the application was started with: the application’s settings file, each module file inlined in its `modules` list, passwords as `***`. Writing it changes the files. The application checks the change as at start, saves it (the previous file as `.bak`), and then refuses all work until it is restarted: `restart-required`, status `-5`. `hdvisionsystems/lumiscan-calibration/system/control/restart/execute` restarts it. See [Settings on the Data Layer](https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/lumiscan-calibration/settings-on-the-data-layer.html).

**Changed:**

- **The example module is `example`, and it reads AI Object Matching.** The example module file is now `example.json`, so the module is `hdvisionsystems/lumiscan-calibration/example`, no longer `.../lumiscan-calibration-example-module`. Its `stream` section, with a `remap` step, reads the results of AI Object Matching’s example module, also `example`, from the start, and writes the points to the regular output too. A settings folder that already has its files keeps them. See [Module Configuration File](https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/lumiscan-calibration/module-configuration-file.html).
- **`reset` reloads the module.** A reset reads the module configuration file and its TIFF file again, so a corrected file takes effect without a restart. If it cannot be loaded, the module reports `-2` and has no lookup table until a reset succeeds, instead of transforming with the old one.
- **An error status stays until the next request.** It used to be replaced by `0` within about 100 ms, before a client could read it.
- The `bilateralInterpolation` interpolation method is now accepted by the settings schema.
- Module configuration files may contain comments, as the application settings file may.

**Bugfix:**

- **A missing TIFF file no longer crashes the application at start.** The module is served and reports status `-2` (`invalidSetting`), and `control/transform/ready` stays `false`, until its files are corrected and it is reset.
- **The application no longer waits for ever on a client that does not lower `request`** when it is asked to stop, and a reset requested meanwhile is served.
- `control/reset/request` was never acknowledged. A reset now follows the handshake.
- An invalid application settings file is written to the log, and the application stops, instead of crashing.

# v 1.2.1 - 2025.07.01 – LumiScan Calibration

URL: https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/release-notes/v1-2-1-2025-07-01.html

**Breaking Changes**

- LumiScan-Calibration name in datalayer was called `lumiscan-cam-calibration`. Now is called **`lumiscan-calibration`**

**Added**

- Usability: support internal storage, SD Card, USB storage
- Functionality: support array transform

**Bugfix**

- High CPU usage when shutting down program if no license detected, which paralyzes CtrlX Core.

# LumiScan Calibration

URL: https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/index.html

|   |   |   |
| --- | --- | --- |
| ![Camera above a calibration plate on the work plane](https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/_images/intro/step-1.svg)<br><br>**Calibrate the work plane once.** With a calibration plate; HDVS returns a TIFF file. | ![Camera image with a marked position at 812, 455 pixels](https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/_images/intro/step-2.svg)<br><br>**Take a position in pixels.** For example a part found by a LumiScan vision app. | Example result<br><br><br><br><br><br><br>x<br>412.6<br><br><br>y<br>118.2<br><br><br>z<br>0.0<br><br><br>Module<br>cell-1<br><br>**Get 3D coordinates on the plane.** Ready for the robot to pick or place. |

LumiScan Calibration converts 2D image coordinates into 3D coordinates on a calibrated plane, so positions found in camera images map to real-world coordinates. You calibrate the plane once with a calibration plate; afterwards every pixel position a LumiScan vision app reports can be transformed, one point at a time or as an array. This is what robots need for bin picking and placing parts, on ctrlX OS or a Windows or Ubuntu PC.

For licensing, see [Licence](https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/lumiscan-calibration/requirements.html#licence). Questions or an error message? See the [FAQ](https://docs.hdvisionsystems.com/en/lumiscan-calibration/2.0.0/faq.html).
