Skip to content

Commit c43a839

Browse files
committed
Update docs
1 parent e0e6de5 commit c43a839

2 files changed

Lines changed: 35 additions & 159 deletions

File tree

docs/contents/specification/annotation-sync.md

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ description: "API specification for synchronizing annotations between external s
55

66
> **Note:** Annotation synchronization is currently an experimental feature with partial support in the InOrbit platform.
77
8-
The annotation synchronization framework enables connectors to synchronize waypoint annotations between external systems and InOrbit's Config API.
8+
The annotation synchronization feature enables connectors to synchronize waypoint annotations between external systems and InOrbit's Config API.
99

1010
For Config API models and client, see [Config API](config-api).
1111

@@ -30,10 +30,6 @@ config = AnnotationSyncConfig(
3030
)
3131
```
3232

33-
**Note**: `frame_id` is not configured. The framework automatically starts sync for each unique `frame_id` as robot poses are published.
34-
35-
**Note**: The ownership signature property is `syncOrigin`, with value set to `ConnectorConfig.connector_type`. The manager automatically injects this.
36-
3733
## Interfaces
3834

3935
### ExternalAnnotationProvider[TExternalPosition]
@@ -90,7 +86,7 @@ manager = AnnotationSyncManager(
9086
)
9187
```
9288

93-
**Note**: The framework creates manager instances automatically when new `frame_id`s are detected.
89+
The connector creates manager instances automatically when new `frame_id`s are detected.
9490

9591
### Methods
9692

docs/contents/usage/annotation-sync.md

Lines changed: 33 additions & 153 deletions
Original file line numberDiff line numberDiff line change
@@ -9,110 +9,57 @@ This guide explains how to enable and configure annotation synchronization betwe
99

1010
## Terminology
1111

12-
- **Annotation**: An InOrbit `SpatialAnnotation` object. Currently, we support waypoint annotations (`spec.type == "waypoint"`).
12+
- **Annotation**: An InOrbit `SpatialAnnotation` object. Currently, only waypoint annotations are supported.
1313
- **Position**: A waypoint/location in the external system.
14-
- **External system**: Fleet manager or robot software the connector integrates with.
14+
- **External system**: The software the connector interacts with (fleet manager, robot software).
1515

1616
## Overview
1717

18-
Annotation synchronization keeps positions/waypoints in sync between:
19-
- Your **external system** (e.g., MiR Fleet, Bluebotics, robot software)
20-
- **InOrbit's Config API** (SpatialAnnotation objects)
18+
Annotation synchronization keeps positions/waypoints in sync between your external system and the InOrbit platform.
2119

2220
## Sync Modes
2321

24-
| Mode | Direction | Description |
25-
|------|-----------|-------------|
22+
| Mode | Direction | Description |
23+
| --------------------- | ------------------ | ---------------------------------- |
2624
| `external_to_inorbit` | External → InOrbit | External system is source of truth |
27-
| `inorbit_to_external` | InOrbit → External | InOrbit is source of truth |
25+
| `inorbit_to_external` | InOrbit → External | InOrbit is source of truth |
2826

2927
## Configuration
3028

31-
Annotation sync is configured at the `ConnectorConfig` level:
29+
Annotation synchronization is configured via the connector YAML configuration file:
3230

3331
```yaml
34-
# connector-config.yaml
35-
36-
api_key: ${INORBIT_API_KEY}
37-
rest_api_url: ${INORBIT_REST_API_URL}
38-
account_id: ${INORBIT_ACCOUNT_ID}
39-
connector_type: my_connector
40-
41-
# Annotation synchronization (framework-level feature)
32+
...
33+
# Annotation synchronization
4234
annotation_sync:
4335
enabled: true
4436
mode: external_to_inorbit
4537
sync_interval_seconds: 300
4638

4739
# InOrbit scope settings
48-
location_id: "facility-location-id"
49-
50-
# Connector-specific settings
51-
connector_config:
52-
host: 192.168.1.50
40+
location_id: "location-tag-id"
41+
...
5342
```
5443

55-
**Note**: `frame_id` is not configured statically. The framework automatically starts
56-
sync for each frame_id as robot poses are published, supporting fleet connectors with
57-
robots on multiple maps.
58-
59-
`rest_api_url` points to the InOrbit REST API used by the Config API. It defaults to
60-
the edge SDK's REST API base URL and can be overridden with `INORBIT_REST_API_URL`.
44+
The connector automatically starts annotation synchronization for each frame_id as robot poses are published, enabling fleet integrations with
45+
robots operating on multiple maps.
6146

6247
### Configuration Fields
6348

64-
| Field | Required | Default | Description |
65-
|-------|----------|---------|-------------|
66-
| `enabled` | No | `false` | Enable annotation sync |
67-
| `mode` | No | `external_to_inorbit` | Sync mode |
68-
| `sync_interval_seconds` | No | `300` | Interval between syncs |
69-
| `location_id` | Yes* | - | Location tag ID for scoping |
70-
71-
*Required when `enabled` is `true`. `account_id` must also be set in `ConnectorConfig`.
72-
73-
**Dynamic frame_id**: The framework automatically detects new frame_ids when robot poses
74-
are published and starts sync for each unique frame. This supports fleet connectors
75-
where robots operate on multiple maps.
76-
77-
## Choosing the Right Mode
78-
79-
### External to InOrbit (`external_to_inorbit`)
80-
81-
Use when your external system is the source of truth for positions.
82-
83-
**Behavior**:
84-
- Fetches all positions from external system
85-
- Creates/updates matching waypoint annotations in InOrbit
86-
- Marks stale annotations for deletion
87-
88-
**Best for**:
89-
- Operators who manage waypoints in the external system's UI
90-
- Systems where the external system has authoritative position data
91-
92-
### InOrbit to External (`inorbit_to_external`)
93-
94-
Use when InOrbit is the source of truth for waypoints.
95-
96-
**Behavior**:
97-
- Fetches waypoint annotations from InOrbit Config API
98-
- Creates/updates matching positions in external system
99-
- Only manages positions derived from owned annotations
100-
101-
**Best for**:
102-
- Operators who manage waypoints via InOrbit's map editor
103-
- Centralized waypoint management
49+
| Field | Required | Default | Description |
50+
| ----------------------- | -------- | --------------------- | --------------------------- |
51+
| `enabled` | No | `false` | Enable annotation sync |
52+
| `mode` | No | `external_to_inorbit` | Sync mode |
53+
| `sync_interval_seconds` | No | `300` | Interval between syncs |
54+
| `location_id` | Yes* | - | Location tag ID for scoping |
10455

10556
## Ownership Signatures
10657

10758
The sync uses **signature properties** to identify annotations it manages:
10859

109-
The ownership signature uses a fixed property name (`syncOrigin`) and the connector type as value:
60+
The ownership signature uses a fixed property name (`syncOrigin`) and the `connector_type` as value.
11061

111-
```yaml
112-
connector_type: my-connector
113-
```
114-
115-
This adds a property to each synced annotation:
62+
This adds a property to each synchronized annotation:
11663

11764
```json
11865
{
@@ -124,41 +71,29 @@ This adds a property to each synced annotation:
12471
}
12572
```
12673

127-
**Why this matters**:
128-
- Prevents deletion of manually created annotations
129-
- Enables multiple connectors to manage separate annotation sets
130-
- Provides clear ownership tracking
74+
This prevents the deletion of manually created annotations and enables multiple connectors to manage separate annotation sets.
13175

132-
## Implementing in Your Connector
76+
## Usage
13377

134-
### 1. Define Position Model (Pydantic BaseModel)
135-
136-
External positions **must** be Pydantic `BaseModel` subclasses. This is required for:
137-
- Type-safe serialization via `model_dump()`
138-
- Automatic change detection in sync operations
78+
1. Define a Pydantic model for your external positions. This is required for type-safe serialization via `model_dump()` and automatic change detection in sync operations.
13979

14080
```python
14181
from pydantic import BaseModel
14282

14383
class MyPosition(BaseModel):
144-
"""External system position model (must inherit from BaseModel)."""
84+
"""External system position model."""
14585
id: str
14686
name: str
14787
x: float
14888
y: float
14989
orientation: float
15090
```
15191

152-
### 2. Implement ExternalAnnotationProvider
153-
154-
Provides CRUD operations for your external system's positions:
92+
2. Implement the `ExternalAnnotationProvider` protocol.
15593

15694
```python
15795
class MyPositionProvider:
158-
"""Implements ExternalAnnotationProvider protocol."""
159-
160-
def __init__(self, client):
161-
self._client = client
96+
"""Provides CRUD operations for your external system's positions."""
16297

16398
async def list_positions(self, frame_id: str) -> list[MyPosition]:
16499
"""Fetch positions for the given frame_id (map).
@@ -186,19 +121,11 @@ class MyPositionProvider:
186121
await self._client.delete_position(position_id)
187122
```
188123

189-
### 3. Implement AnnotationConverter
190-
191-
Converts between positions and waypoint annotations:
124+
3. Implement the `AnnotationConverter` protocol.
192125

193126
```python
194-
from inorbit_connector.annotation_sync.models import (
195-
SpatialAnnotationData,
196-
WaypointAnnotationSpec,
197-
WaypointData,
198-
)
199-
200127
class MyAnnotationConverter:
201-
"""Implements AnnotationConverter protocol."""
128+
"""Converts between positions and waypoint annotations."""
202129

203130
def position_to_annotation(
204131
self, position: MyPosition, frame_id: str
@@ -240,71 +167,24 @@ class MyAnnotationConverter:
240167
return position.id
241168
```
242169

243-
### 4. Framework Creates Sync Managers Per Frame
244-
245-
The framework automatically creates `AnnotationSyncManager` instances for each unique
246-
`frame_id` as robot poses are published. You don't need to create managers directly.
247-
248-
**How it works**:
249-
1. When `publish_robot_pose(robot_id, x, y, yaw, frame_id)` is called
250-
2. If `frame_id` is new (not seen before), the framework creates a sync manager for it
251-
3. The manager calls `provider.list_positions(frame_id)` to get positions for that map
252-
4. The manager calls `converter.position_to_annotation(position, frame_id)` to convert
253-
254-
### 5. Integrate with Connector
255-
256-
Register the implementations and let the framework manage initialization and start/stop:
170+
4. Register the provider and converter with the connector.
257171

258172
```python
259173
class MyConnector(FleetConnector):
260174
def __init__(self, config):
261175
super().__init__(config)
262176

263-
# Create provider and converter (frame_id is handled dynamically)
264-
provider = MyPositionProvider(self._my_client)
265-
converter = MyAnnotationConverter()
266-
267-
# Register with framework - sync starts automatically per frame_id
268-
self.register_annotation_sync(provider, converter)
269-
```
270-
271-
**Note**: Always register the provider and converter. The framework checks
272-
`annotation_sync.enabled` to decide whether to actually run the sync.
273-
274-
## Monitoring Sync Operations
275-
276-
The sync manager logs operations at various levels:
277-
278-
| Level | What's Logged |
279-
|-------|---------------|
280-
| INFO | Sync start/complete, counts |
281-
| DEBUG | Individual create/update/delete |
282-
| WARNING | Skipped operations, missing data |
283-
| ERROR | Sync failures with stack traces |
284-
285-
Example log output:
286-
287-
```
288-
INFO - Starting external → InOrbit annotation sync
289-
DEBUG - Fetched 42 positions from external system
290-
INFO - Sync complete: 5 created, 3 updated, 34 up to date, 0 to delete
177+
# Register provider and converter
178+
self.register_annotation_sync(MyPositionProvider(), MyAnnotationConverter())
291179
```
292180

293181
## Troubleshooting
294182

295-
### Annotations not syncing
296-
297183
1. **Check configuration**: Ensure `enabled: true` and valid `mode`
298184
2. **Verify API key**: Must have permissions for Config API
299-
3. **Check auth method**: Config API requires `api_key` (robot keys are not supported)
185+
3. **Check auth method**: The Config API requires an `api_key`, not an `inorbit_robot_key`
300186
4. **Check scope**: Ensure `account_id` and `location_id` are correct
301187

302-
### Manual annotations being deleted
303-
304-
Check your ownership signature:
305-
- Manually created annotations won't have the signature property
306-
- Only annotations with matching signature are managed by sync
307-
308188
## See Also
309189

310190
- [Annotation Sync API Reference](../specification/annotation-sync)

0 commit comments

Comments
 (0)