rainbow-rb-sdk 0.0.9.dev16__tar.gz → 0.0.9.dev18__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {rainbow_rb_sdk-0.0.9.dev16/src/rainbow_rb_sdk.egg-info → rainbow_rb_sdk-0.0.9.dev18}/PKG-INFO +138 -7
- rainbow_rb_sdk-0.0.9.dev16/PKG-INFO → rainbow_rb_sdk-0.0.9.dev18/README.md +132 -15
- {rainbow_rb_sdk-0.0.9.dev16 → rainbow_rb_sdk-0.0.9.dev18}/pyproject.toml +7 -7
- {rainbow_rb_sdk-0.0.9.dev16 → rainbow_rb_sdk-0.0.9.dev18}/src/rainbow/rb_sdk/amr_sdk/amr_setting.py +43 -67
- {rainbow_rb_sdk-0.0.9.dev16 → rainbow_rb_sdk-0.0.9.dev18}/src/rainbow/rb_sdk/base.py +23 -4
- {rainbow_rb_sdk-0.0.9.dev16 → rainbow_rb_sdk-0.0.9.dev18}/src/rainbow/rb_sdk/manipulate_sdk/manipulate_config.py +37 -37
- {rainbow_rb_sdk-0.0.9.dev16 → rainbow_rb_sdk-0.0.9.dev18}/src/rainbow/rb_sdk/manipulate_sdk/manipulate_io.py +36 -36
- {rainbow_rb_sdk-0.0.9.dev16 → rainbow_rb_sdk-0.0.9.dev18}/src/rainbow/rb_sdk/manipulate_sdk/manipulate_maintenance.py +13 -13
- {rainbow_rb_sdk-0.0.9.dev16 → rainbow_rb_sdk-0.0.9.dev18}/src/rainbow/rb_sdk/manipulate_sdk/manipulate_move.py +237 -40
- {rainbow_rb_sdk-0.0.9.dev16 → rainbow_rb_sdk-0.0.9.dev18}/src/rainbow/rb_sdk/manipulate_sdk/manipulate_point.py +1 -1
- {rainbow_rb_sdk-0.0.9.dev16 → rainbow_rb_sdk-0.0.9.dev18}/src/rainbow/rb_sdk/manipulate_sdk/manipulate_program.py +3 -3
- {rainbow_rb_sdk-0.0.9.dev16 → rainbow_rb_sdk-0.0.9.dev18}/src/rainbow/rb_sdk/manipulate_sdk/manipulate_service.py +124 -38
- {rainbow_rb_sdk-0.0.9.dev16 → rainbow_rb_sdk-0.0.9.dev18}/src/rainbow/rb_sdk/manipulate_sdk/schema/manipulate_move_schema.py +2 -2
- rainbow_rb_sdk-0.0.9.dev16/README.md → rainbow_rb_sdk-0.0.9.dev18/src/rainbow_rb_sdk.egg-info/PKG-INFO +146 -1
- rainbow_rb_sdk-0.0.9.dev18/src/rainbow_rb_sdk.egg-info/requires.txt +6 -0
- rainbow_rb_sdk-0.0.9.dev16/src/rainbow_rb_sdk.egg-info/requires.txt +0 -6
- {rainbow_rb_sdk-0.0.9.dev16 → rainbow_rb_sdk-0.0.9.dev18}/setup.cfg +0 -0
- {rainbow_rb_sdk-0.0.9.dev16 → rainbow_rb_sdk-0.0.9.dev18}/src/rainbow/rb_sdk/__init__.py +0 -0
- {rainbow_rb_sdk-0.0.9.dev16 → rainbow_rb_sdk-0.0.9.dev18}/src/rainbow/rb_sdk/amr.py +0 -0
- {rainbow_rb_sdk-0.0.9.dev16 → rainbow_rb_sdk-0.0.9.dev18}/src/rainbow/rb_sdk/amr_sdk/__init__.py +0 -0
- {rainbow_rb_sdk-0.0.9.dev16 → rainbow_rb_sdk-0.0.9.dev18}/src/rainbow/rb_sdk/amr_sdk/amr_accessory.py +0 -0
- {rainbow_rb_sdk-0.0.9.dev16 → rainbow_rb_sdk-0.0.9.dev18}/src/rainbow/rb_sdk/amr_sdk/amr_capability.py +0 -0
- {rainbow_rb_sdk-0.0.9.dev16 → rainbow_rb_sdk-0.0.9.dev18}/src/rainbow/rb_sdk/amr_sdk/amr_control.py +0 -0
- {rainbow_rb_sdk-0.0.9.dev16 → rainbow_rb_sdk-0.0.9.dev18}/src/rainbow/rb_sdk/amr_sdk/amr_file.py +0 -0
- {rainbow_rb_sdk-0.0.9.dev16 → rainbow_rb_sdk-0.0.9.dev18}/src/rainbow/rb_sdk/amr_sdk/amr_localization.py +0 -0
- {rainbow_rb_sdk-0.0.9.dev16 → rainbow_rb_sdk-0.0.9.dev18}/src/rainbow/rb_sdk/amr_sdk/amr_map.py +0 -0
- {rainbow_rb_sdk-0.0.9.dev16 → rainbow_rb_sdk-0.0.9.dev18}/src/rainbow/rb_sdk/amr_sdk/amr_move.py +0 -0
- {rainbow_rb_sdk-0.0.9.dev16 → rainbow_rb_sdk-0.0.9.dev18}/src/rainbow/rb_sdk/amr_sdk/amr_program.py +0 -0
- {rainbow_rb_sdk-0.0.9.dev16 → rainbow_rb_sdk-0.0.9.dev18}/src/rainbow/rb_sdk/amr_sdk/amr_status.py +0 -0
- {rainbow_rb_sdk-0.0.9.dev16 → rainbow_rb_sdk-0.0.9.dev18}/src/rainbow/rb_sdk/amr_sdk/schema/__init__.py +0 -0
- {rainbow_rb_sdk-0.0.9.dev16 → rainbow_rb_sdk-0.0.9.dev18}/src/rainbow/rb_sdk/base_sdk/__init__.py +0 -0
- {rainbow_rb_sdk-0.0.9.dev16 → rainbow_rb_sdk-0.0.9.dev18}/src/rainbow/rb_sdk/base_sdk/base_schema.py +0 -0
- {rainbow_rb_sdk-0.0.9.dev16 → rainbow_rb_sdk-0.0.9.dev18}/src/rainbow/rb_sdk/manipulate.py +0 -0
- {rainbow_rb_sdk-0.0.9.dev16 → rainbow_rb_sdk-0.0.9.dev18}/src/rainbow/rb_sdk/manipulate_sdk/__init__.py +0 -0
- {rainbow_rb_sdk-0.0.9.dev16 → rainbow_rb_sdk-0.0.9.dev18}/src/rainbow/rb_sdk/manipulate_sdk/manipulate_get_data.py +0 -0
- {rainbow_rb_sdk-0.0.9.dev16 → rainbow_rb_sdk-0.0.9.dev18}/src/rainbow/rb_sdk/manipulate_sdk/manipulate_state.py +0 -0
- {rainbow_rb_sdk-0.0.9.dev16 → rainbow_rb_sdk-0.0.9.dev18}/src/rainbow/rb_sdk/manipulate_sdk/schema/__init__.py +0 -0
- {rainbow_rb_sdk-0.0.9.dev16 → rainbow_rb_sdk-0.0.9.dev18}/src/rainbow/rb_sdk/manipulate_sdk/schema/manipulate_config_schema.py +0 -0
- {rainbow_rb_sdk-0.0.9.dev16 → rainbow_rb_sdk-0.0.9.dev18}/src/rainbow/rb_sdk/manipulate_sdk/schema/manipulate_io_schema.py +0 -0
- {rainbow_rb_sdk-0.0.9.dev16 → rainbow_rb_sdk-0.0.9.dev18}/src/rainbow/rb_sdk/manipulate_sdk/schema/manipulate_program_schema.py +0 -0
- {rainbow_rb_sdk-0.0.9.dev16 → rainbow_rb_sdk-0.0.9.dev18}/src/rainbow/rb_sdk/program_sdk/__init__.py +0 -0
- {rainbow_rb_sdk-0.0.9.dev16 → rainbow_rb_sdk-0.0.9.dev18}/src/rainbow/rb_sdk/program_sdk/client_modules.pyi +0 -0
- {rainbow_rb_sdk-0.0.9.dev16 → rainbow_rb_sdk-0.0.9.dev18}/src/rainbow/rb_sdk/program_sdk/program.py +0 -0
- {rainbow_rb_sdk-0.0.9.dev16 → rainbow_rb_sdk-0.0.9.dev18}/src/rainbow/rb_sdk/program_sdk/program_interface.py +0 -0
- {rainbow_rb_sdk-0.0.9.dev16 → rainbow_rb_sdk-0.0.9.dev18}/src/rainbow/rb_sdk/program_sdk/test_binding.py +0 -0
- {rainbow_rb_sdk-0.0.9.dev16 → rainbow_rb_sdk-0.0.9.dev18}/src/rainbow/rb_sdk/rby1.py +0 -0
- {rainbow_rb_sdk-0.0.9.dev16 → rainbow_rb_sdk-0.0.9.dev18}/src/rainbow/rb_sdk/rby1_sdk/__init__.py +0 -0
- {rainbow_rb_sdk-0.0.9.dev16 → rainbow_rb_sdk-0.0.9.dev18}/src/rainbow/rb_sdk/rby1_sdk/base.py +0 -0
- {rainbow_rb_sdk-0.0.9.dev16 → rainbow_rb_sdk-0.0.9.dev18}/src/rainbow/rb_sdk/rby1_sdk/client.py +0 -0
- {rainbow_rb_sdk-0.0.9.dev16 → rainbow_rb_sdk-0.0.9.dev18}/src/rainbow/rb_sdk/rby1_sdk/config.py +0 -0
- {rainbow_rb_sdk-0.0.9.dev16 → rainbow_rb_sdk-0.0.9.dev18}/src/rainbow/rb_sdk/rby1_sdk/control.py +0 -0
- {rainbow_rb_sdk-0.0.9.dev16 → rainbow_rb_sdk-0.0.9.dev18}/src/rainbow/rb_sdk/rby1_sdk/exceptions.py +0 -0
- {rainbow_rb_sdk-0.0.9.dev16 → rainbow_rb_sdk-0.0.9.dev18}/src/rainbow/rb_sdk/rby1_sdk/state.py +0 -0
- {rainbow_rb_sdk-0.0.9.dev16 → rainbow_rb_sdk-0.0.9.dev18}/src/rainbow/rb_sdk/schema/__init__.py +0 -0
- {rainbow_rb_sdk-0.0.9.dev16 → rainbow_rb_sdk-0.0.9.dev18}/src/rainbow/rb_sdk/schema/amr_schema.py +0 -0
- {rainbow_rb_sdk-0.0.9.dev16 → rainbow_rb_sdk-0.0.9.dev18}/src/rainbow/rb_sdk/schema/base_schema.py +0 -0
- {rainbow_rb_sdk-0.0.9.dev16 → rainbow_rb_sdk-0.0.9.dev18}/src/rainbow/rb_sdk/schema/manipulate_schema.py +0 -0
- {rainbow_rb_sdk-0.0.9.dev16 → rainbow_rb_sdk-0.0.9.dev18}/src/rainbow/rb_sdk/schema/program_schema.py +0 -0
- {rainbow_rb_sdk-0.0.9.dev16 → rainbow_rb_sdk-0.0.9.dev18}/src/rainbow_rb_sdk.egg-info/SOURCES.txt +0 -0
- {rainbow_rb_sdk-0.0.9.dev16 → rainbow_rb_sdk-0.0.9.dev18}/src/rainbow_rb_sdk.egg-info/dependency_links.txt +0 -0
- {rainbow_rb_sdk-0.0.9.dev16 → rainbow_rb_sdk-0.0.9.dev18}/src/rainbow_rb_sdk.egg-info/top_level.txt +0 -0
{rainbow_rb_sdk-0.0.9.dev16/src/rainbow_rb_sdk.egg-info → rainbow_rb_sdk-0.0.9.dev18}/PKG-INFO
RENAMED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: rainbow-rb-sdk
|
|
3
|
-
Version: 0.0.9.
|
|
3
|
+
Version: 0.0.9.dev18
|
|
4
4
|
Summary: Rainbow Robotics 통합 Python SDK — AMR, 매니퓰레이터, RB-Y1 휴머노이드와 Rainbow Robot Service(common) 연동
|
|
5
5
|
Author-email: Derek <dfd1123@rainbow-robotics.com>
|
|
6
6
|
Requires-Python: <3.13,>=3.12
|
|
7
7
|
Description-Content-Type: text/markdown
|
|
8
|
-
Requires-Dist: rainbow-rb-utils==0.0.9.
|
|
9
|
-
Requires-Dist: rainbow-rb-zenoh==0.0.9.
|
|
10
|
-
Requires-Dist: rainbow-rb-flat-buffers==0.0.9.
|
|
11
|
-
Requires-Dist: rainbow-rb-schemas==0.0.9.
|
|
12
|
-
Requires-Dist: rainbow-rb-log==0.0.9.
|
|
8
|
+
Requires-Dist: rainbow-rb-utils==0.0.9.dev18
|
|
9
|
+
Requires-Dist: rainbow-rb-zenoh==0.0.9.dev18
|
|
10
|
+
Requires-Dist: rainbow-rb-flat-buffers==0.0.9.dev18
|
|
11
|
+
Requires-Dist: rainbow-rb-schemas==0.0.9.dev18
|
|
12
|
+
Requires-Dist: rainbow-rb-log==0.0.9.dev18
|
|
13
13
|
Requires-Dist: rby1-sdk>=0.9.1
|
|
14
14
|
|
|
15
15
|
# rb_sdk
|
|
@@ -326,6 +326,137 @@ RBBaseSDK.close_all_for_pid() # 현재 프로세스의 모든 SDK 인스
|
|
|
326
326
|
|
|
327
327
|
---
|
|
328
328
|
|
|
329
|
-
## 11.
|
|
329
|
+
## 11. Subscribe / Queryable
|
|
330
|
+
|
|
331
|
+
SDK를 상속하거나 직접 사용해 **Zenoh 이벤트를 수신(subscribe)** 하거나 **RPC 응답자(queryable)** 를 등록할 수 있습니다.
|
|
332
|
+
|
|
333
|
+
### 11-1. `zenoh_subscribe` — 토픽 구독 (데코레이터)
|
|
334
|
+
|
|
335
|
+
```python
|
|
336
|
+
from rb_sdk import RBManipulateSDK
|
|
337
|
+
from rb_zenoh.schema import SubscribeOptions, OverflowPolicy
|
|
338
|
+
|
|
339
|
+
sdk = RBManipulateSDK()
|
|
340
|
+
|
|
341
|
+
# dict 페이로드로 수신 (기본)
|
|
342
|
+
@sdk.zenoh_subscribe("amr/AMR001/status")
|
|
343
|
+
def on_status(*, dict_payload: dict | None, **kwargs):
|
|
344
|
+
print("status:", dict_payload)
|
|
345
|
+
|
|
346
|
+
# FlatBuffer 오브젝트로 수신
|
|
347
|
+
from rb_flat_buffers.IPC.MoveStatus import MoveStatusT
|
|
348
|
+
|
|
349
|
+
@sdk.zenoh_subscribe(
|
|
350
|
+
"amr/AMR001/moveStatus",
|
|
351
|
+
flatbuffer_obj_t=MoveStatusT,
|
|
352
|
+
opts=SubscribeOptions(
|
|
353
|
+
dispatch="queue",
|
|
354
|
+
overflow=OverflowPolicy.LATEST_ONLY,
|
|
355
|
+
parse_dict_payload=False,
|
|
356
|
+
),
|
|
357
|
+
)
|
|
358
|
+
def on_move_status(*, obj_payload: MoveStatusT, **kwargs):
|
|
359
|
+
print("move status:", obj_payload)
|
|
360
|
+
|
|
361
|
+
# mv를 직접 받아 수동으로 파싱하는 패턴 (flatbuffer_obj_t 미지정)
|
|
362
|
+
from rb_flat_buffers.IPC.State_Core import State_Core
|
|
363
|
+
|
|
364
|
+
@sdk.zenoh_subscribe(
|
|
365
|
+
"C500920/state_core",
|
|
366
|
+
opts=SubscribeOptions(
|
|
367
|
+
dispatch="queue",
|
|
368
|
+
overflow=OverflowPolicy.LATEST_ONLY,
|
|
369
|
+
parse_dict_payload=False,
|
|
370
|
+
),
|
|
371
|
+
)
|
|
372
|
+
def on_state_core(*, mv=None, **kwargs):
|
|
373
|
+
if mv is None:
|
|
374
|
+
return
|
|
375
|
+
obj = State_Core.GetRootAs(mv, 0)
|
|
376
|
+
print("motion mode:", obj.MotionMode())
|
|
377
|
+
```
|
|
378
|
+
|
|
379
|
+
#### `zenoh_subscribe` 인자
|
|
380
|
+
|
|
381
|
+
| 인자 | 타입 | 기본 | 설명 |
|
|
382
|
+
|---|---|---|---|
|
|
383
|
+
| `topic` | `str` | (필수) | Zenoh key expression (예: `"amr/{model}/status"`) |
|
|
384
|
+
| `flatbuffer_obj_t` | FlatBuffer T 클래스 \| `None` | `None` | FlatBuffer로 역직렬화할 때 지정. `None`이면 콜백에 `mv: memoryview` 전달 |
|
|
385
|
+
| `opts` | `SubscribeOptions \| None` | `None` | 디스패치 / 오버플로우 옵션 |
|
|
386
|
+
|
|
387
|
+
#### `SubscribeOptions` 필드
|
|
388
|
+
|
|
389
|
+
| 필드 | 기본 | 설명 |
|
|
390
|
+
|---|---|---|
|
|
391
|
+
| `dispatch` | `"immediate"` | `"immediate"`: 수신 스레드에서 바로 콜백. `"queue"`: C++ bounded queue + 전용 dispatch 스레드 |
|
|
392
|
+
| `parse_dict_payload` | `True` | FlatBuffer 수신 시 `False`로 지정 |
|
|
393
|
+
| `overflow` | `DROP_OLDEST` | `DROP_OLDEST` / `DROP_NEW` / `LATEST_ONLY` |
|
|
394
|
+
| `maxsize` | `50` | `"queue"` 모드의 C++ 큐 최대 크기 |
|
|
395
|
+
| `rate_limit_per_sec` | `None` | 초당 최대 콜백 호출 수 |
|
|
396
|
+
| `sample_every` | `1` | N개 중 1개만 전달 (1 = 전부) |
|
|
397
|
+
| `max_async_inflight` | `1` | async 콜백 동시 실행 허용 수 |
|
|
398
|
+
|
|
399
|
+
#### 직접 subscribe (handle 보관이 필요한 경우)
|
|
400
|
+
|
|
401
|
+
데코레이터 대신 `zenoh_client.subscribe()`를 직접 호출하면 handle을 직접 관리할 수 있습니다.
|
|
402
|
+
|
|
403
|
+
```python
|
|
404
|
+
sub_handle = sdk.zenoh_client.subscribe(
|
|
405
|
+
"amr/AMR001/moveStatus",
|
|
406
|
+
callback,
|
|
407
|
+
flatbuffer_obj_t=MoveStatusT,
|
|
408
|
+
options=SubscribeOptions(dispatch="queue", overflow=OverflowPolicy.LATEST_ONLY),
|
|
409
|
+
)
|
|
410
|
+
|
|
411
|
+
# 구독 해제
|
|
412
|
+
sub_handle.close()
|
|
413
|
+
```
|
|
414
|
+
|
|
415
|
+
---
|
|
416
|
+
|
|
417
|
+
### 11-2. `zenoh_queryable` — RPC 응답자 (데코레이터)
|
|
418
|
+
|
|
419
|
+
원격에서 `get(keyexpr)` 요청이 오면 등록된 handler가 호출되어 응답을 반환합니다.
|
|
420
|
+
|
|
421
|
+
```python
|
|
422
|
+
from rb_sdk import RBManipulateSDK
|
|
423
|
+
|
|
424
|
+
sdk = RBManipulateSDK()
|
|
425
|
+
|
|
426
|
+
# dict 요청 (payload 없음) → dict 반환
|
|
427
|
+
# params는 URL query string (예: ?model=C500920)을 파싱한 dict[str, str]
|
|
428
|
+
@sdk.zenoh_queryable("my_service/robot_status")
|
|
429
|
+
def handle_status_query(*, params: dict[str, str]) -> dict:
|
|
430
|
+
return {"status": "ok", "model": params.get("model")}
|
|
431
|
+
|
|
432
|
+
# FlatBuffer 요청 수신 → FlatBuffer 응답
|
|
433
|
+
from rb_flat_buffers.manipulate.RB_Functions import RB_FunctionsT
|
|
434
|
+
|
|
435
|
+
@sdk.zenoh_queryable(
|
|
436
|
+
"my_service/move_j",
|
|
437
|
+
flatbuffer_req_T_class=RB_FunctionsT,
|
|
438
|
+
flatbuffer_res_buf_size=256,
|
|
439
|
+
)
|
|
440
|
+
def handle_move_j(*, req: RB_FunctionsT, params: dict[str, str]) -> RB_FunctionsT:
|
|
441
|
+
res = RB_FunctionsT()
|
|
442
|
+
res.returnValue = 0
|
|
443
|
+
return res
|
|
444
|
+
```
|
|
445
|
+
|
|
446
|
+
#### `zenoh_queryable` 인자
|
|
447
|
+
|
|
448
|
+
| 인자 | 타입 | 기본 | 설명 |
|
|
449
|
+
|---|---|---|---|
|
|
450
|
+
| `keyexpr` | `str` | (필수) | Zenoh key expression (예: `"my_service/status"`) |
|
|
451
|
+
| `flatbuffer_req_T_class` | FlatBuffer T 클래스 \| `None` | `None` | 요청 페이로드를 FlatBuffer로 역직렬화할 때 지정 |
|
|
452
|
+
| `flatbuffer_res_buf_size` | `int \| None` | `None` | FlatBuffer 응답 직렬화 버퍼 크기(바이트). FlatBuffer 응답 시 필수 |
|
|
453
|
+
|
|
454
|
+
#### 중복 등록 방지
|
|
455
|
+
|
|
456
|
+
같은 `keyexpr`로 이미 등록된 queryable이 있으면 경고 메시지를 출력하고 기존 handler를 유지합니다. SDK `close()` 시 자동 해제됩니다.
|
|
457
|
+
|
|
458
|
+
---
|
|
459
|
+
|
|
460
|
+
## 12. 라이선스 / 문의
|
|
330
461
|
|
|
331
462
|
© Rainbow Robotics. 내부 이슈/문의: [GitHub Issues](https://github.com/rainbow-mobile/rainbow-release-apps/issues)
|
|
@@ -1,17 +1,3 @@
|
|
|
1
|
-
Metadata-Version: 2.4
|
|
2
|
-
Name: rainbow-rb-sdk
|
|
3
|
-
Version: 0.0.9.dev16
|
|
4
|
-
Summary: Rainbow Robotics 통합 Python SDK — AMR, 매니퓰레이터, RB-Y1 휴머노이드와 Rainbow Robot Service(common) 연동
|
|
5
|
-
Author-email: Derek <dfd1123@rainbow-robotics.com>
|
|
6
|
-
Requires-Python: <3.13,>=3.12
|
|
7
|
-
Description-Content-Type: text/markdown
|
|
8
|
-
Requires-Dist: rainbow-rb-utils==0.0.9.dev16
|
|
9
|
-
Requires-Dist: rainbow-rb-zenoh==0.0.9.dev16
|
|
10
|
-
Requires-Dist: rainbow-rb-flat-buffers==0.0.9.dev16
|
|
11
|
-
Requires-Dist: rainbow-rb-schemas==0.0.9.dev16
|
|
12
|
-
Requires-Dist: rainbow-rb-log==0.0.9.dev16
|
|
13
|
-
Requires-Dist: rby1-sdk>=0.9.1
|
|
14
|
-
|
|
15
1
|
# rb_sdk
|
|
16
2
|
|
|
17
3
|
Rainbow Robotics 통합 Python SDK. AMR · Manipulator · RB-Y1 양팔로봇 제어와 Rainbow Robot Service(common) 연동을 단일 API로 제공합니다.
|
|
@@ -326,6 +312,137 @@ RBBaseSDK.close_all_for_pid() # 현재 프로세스의 모든 SDK 인스
|
|
|
326
312
|
|
|
327
313
|
---
|
|
328
314
|
|
|
329
|
-
## 11.
|
|
315
|
+
## 11. Subscribe / Queryable
|
|
316
|
+
|
|
317
|
+
SDK를 상속하거나 직접 사용해 **Zenoh 이벤트를 수신(subscribe)** 하거나 **RPC 응답자(queryable)** 를 등록할 수 있습니다.
|
|
318
|
+
|
|
319
|
+
### 11-1. `zenoh_subscribe` — 토픽 구독 (데코레이터)
|
|
320
|
+
|
|
321
|
+
```python
|
|
322
|
+
from rb_sdk import RBManipulateSDK
|
|
323
|
+
from rb_zenoh.schema import SubscribeOptions, OverflowPolicy
|
|
324
|
+
|
|
325
|
+
sdk = RBManipulateSDK()
|
|
326
|
+
|
|
327
|
+
# dict 페이로드로 수신 (기본)
|
|
328
|
+
@sdk.zenoh_subscribe("amr/AMR001/status")
|
|
329
|
+
def on_status(*, dict_payload: dict | None, **kwargs):
|
|
330
|
+
print("status:", dict_payload)
|
|
331
|
+
|
|
332
|
+
# FlatBuffer 오브젝트로 수신
|
|
333
|
+
from rb_flat_buffers.IPC.MoveStatus import MoveStatusT
|
|
334
|
+
|
|
335
|
+
@sdk.zenoh_subscribe(
|
|
336
|
+
"amr/AMR001/moveStatus",
|
|
337
|
+
flatbuffer_obj_t=MoveStatusT,
|
|
338
|
+
opts=SubscribeOptions(
|
|
339
|
+
dispatch="queue",
|
|
340
|
+
overflow=OverflowPolicy.LATEST_ONLY,
|
|
341
|
+
parse_dict_payload=False,
|
|
342
|
+
),
|
|
343
|
+
)
|
|
344
|
+
def on_move_status(*, obj_payload: MoveStatusT, **kwargs):
|
|
345
|
+
print("move status:", obj_payload)
|
|
346
|
+
|
|
347
|
+
# mv를 직접 받아 수동으로 파싱하는 패턴 (flatbuffer_obj_t 미지정)
|
|
348
|
+
from rb_flat_buffers.IPC.State_Core import State_Core
|
|
349
|
+
|
|
350
|
+
@sdk.zenoh_subscribe(
|
|
351
|
+
"C500920/state_core",
|
|
352
|
+
opts=SubscribeOptions(
|
|
353
|
+
dispatch="queue",
|
|
354
|
+
overflow=OverflowPolicy.LATEST_ONLY,
|
|
355
|
+
parse_dict_payload=False,
|
|
356
|
+
),
|
|
357
|
+
)
|
|
358
|
+
def on_state_core(*, mv=None, **kwargs):
|
|
359
|
+
if mv is None:
|
|
360
|
+
return
|
|
361
|
+
obj = State_Core.GetRootAs(mv, 0)
|
|
362
|
+
print("motion mode:", obj.MotionMode())
|
|
363
|
+
```
|
|
364
|
+
|
|
365
|
+
#### `zenoh_subscribe` 인자
|
|
366
|
+
|
|
367
|
+
| 인자 | 타입 | 기본 | 설명 |
|
|
368
|
+
|---|---|---|---|
|
|
369
|
+
| `topic` | `str` | (필수) | Zenoh key expression (예: `"amr/{model}/status"`) |
|
|
370
|
+
| `flatbuffer_obj_t` | FlatBuffer T 클래스 \| `None` | `None` | FlatBuffer로 역직렬화할 때 지정. `None`이면 콜백에 `mv: memoryview` 전달 |
|
|
371
|
+
| `opts` | `SubscribeOptions \| None` | `None` | 디스패치 / 오버플로우 옵션 |
|
|
372
|
+
|
|
373
|
+
#### `SubscribeOptions` 필드
|
|
374
|
+
|
|
375
|
+
| 필드 | 기본 | 설명 |
|
|
376
|
+
|---|---|---|
|
|
377
|
+
| `dispatch` | `"immediate"` | `"immediate"`: 수신 스레드에서 바로 콜백. `"queue"`: C++ bounded queue + 전용 dispatch 스레드 |
|
|
378
|
+
| `parse_dict_payload` | `True` | FlatBuffer 수신 시 `False`로 지정 |
|
|
379
|
+
| `overflow` | `DROP_OLDEST` | `DROP_OLDEST` / `DROP_NEW` / `LATEST_ONLY` |
|
|
380
|
+
| `maxsize` | `50` | `"queue"` 모드의 C++ 큐 최대 크기 |
|
|
381
|
+
| `rate_limit_per_sec` | `None` | 초당 최대 콜백 호출 수 |
|
|
382
|
+
| `sample_every` | `1` | N개 중 1개만 전달 (1 = 전부) |
|
|
383
|
+
| `max_async_inflight` | `1` | async 콜백 동시 실행 허용 수 |
|
|
384
|
+
|
|
385
|
+
#### 직접 subscribe (handle 보관이 필요한 경우)
|
|
386
|
+
|
|
387
|
+
데코레이터 대신 `zenoh_client.subscribe()`를 직접 호출하면 handle을 직접 관리할 수 있습니다.
|
|
388
|
+
|
|
389
|
+
```python
|
|
390
|
+
sub_handle = sdk.zenoh_client.subscribe(
|
|
391
|
+
"amr/AMR001/moveStatus",
|
|
392
|
+
callback,
|
|
393
|
+
flatbuffer_obj_t=MoveStatusT,
|
|
394
|
+
options=SubscribeOptions(dispatch="queue", overflow=OverflowPolicy.LATEST_ONLY),
|
|
395
|
+
)
|
|
396
|
+
|
|
397
|
+
# 구독 해제
|
|
398
|
+
sub_handle.close()
|
|
399
|
+
```
|
|
400
|
+
|
|
401
|
+
---
|
|
402
|
+
|
|
403
|
+
### 11-2. `zenoh_queryable` — RPC 응답자 (데코레이터)
|
|
404
|
+
|
|
405
|
+
원격에서 `get(keyexpr)` 요청이 오면 등록된 handler가 호출되어 응답을 반환합니다.
|
|
406
|
+
|
|
407
|
+
```python
|
|
408
|
+
from rb_sdk import RBManipulateSDK
|
|
409
|
+
|
|
410
|
+
sdk = RBManipulateSDK()
|
|
411
|
+
|
|
412
|
+
# dict 요청 (payload 없음) → dict 반환
|
|
413
|
+
# params는 URL query string (예: ?model=C500920)을 파싱한 dict[str, str]
|
|
414
|
+
@sdk.zenoh_queryable("my_service/robot_status")
|
|
415
|
+
def handle_status_query(*, params: dict[str, str]) -> dict:
|
|
416
|
+
return {"status": "ok", "model": params.get("model")}
|
|
417
|
+
|
|
418
|
+
# FlatBuffer 요청 수신 → FlatBuffer 응답
|
|
419
|
+
from rb_flat_buffers.manipulate.RB_Functions import RB_FunctionsT
|
|
420
|
+
|
|
421
|
+
@sdk.zenoh_queryable(
|
|
422
|
+
"my_service/move_j",
|
|
423
|
+
flatbuffer_req_T_class=RB_FunctionsT,
|
|
424
|
+
flatbuffer_res_buf_size=256,
|
|
425
|
+
)
|
|
426
|
+
def handle_move_j(*, req: RB_FunctionsT, params: dict[str, str]) -> RB_FunctionsT:
|
|
427
|
+
res = RB_FunctionsT()
|
|
428
|
+
res.returnValue = 0
|
|
429
|
+
return res
|
|
430
|
+
```
|
|
431
|
+
|
|
432
|
+
#### `zenoh_queryable` 인자
|
|
433
|
+
|
|
434
|
+
| 인자 | 타입 | 기본 | 설명 |
|
|
435
|
+
|---|---|---|---|
|
|
436
|
+
| `keyexpr` | `str` | (필수) | Zenoh key expression (예: `"my_service/status"`) |
|
|
437
|
+
| `flatbuffer_req_T_class` | FlatBuffer T 클래스 \| `None` | `None` | 요청 페이로드를 FlatBuffer로 역직렬화할 때 지정 |
|
|
438
|
+
| `flatbuffer_res_buf_size` | `int \| None` | `None` | FlatBuffer 응답 직렬화 버퍼 크기(바이트). FlatBuffer 응답 시 필수 |
|
|
439
|
+
|
|
440
|
+
#### 중복 등록 방지
|
|
441
|
+
|
|
442
|
+
같은 `keyexpr`로 이미 등록된 queryable이 있으면 경고 메시지를 출력하고 기존 handler를 유지합니다. SDK `close()` 시 자동 해제됩니다.
|
|
443
|
+
|
|
444
|
+
---
|
|
445
|
+
|
|
446
|
+
## 12. 라이선스 / 문의
|
|
330
447
|
|
|
331
448
|
© Rainbow Robotics. 내부 이슈/문의: [GitHub Issues](https://github.com/rainbow-mobile/rainbow-release-apps/issues)
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "rainbow-rb-sdk"
|
|
7
|
-
version = "0.0.9.
|
|
7
|
+
version = "0.0.9.dev18"
|
|
8
8
|
requires-python = ">=3.12,<3.13"
|
|
9
9
|
description = "Rainbow Robotics 통합 Python SDK — AMR, 매니퓰레이터, RB-Y1 휴머노이드와 Rainbow Robot Service(common) 연동"
|
|
10
10
|
authors = [
|
|
@@ -13,11 +13,11 @@ authors = [
|
|
|
13
13
|
readme = "README.md"
|
|
14
14
|
|
|
15
15
|
dependencies = [
|
|
16
|
-
"rainbow-rb-utils==0.0.9.
|
|
17
|
-
"rainbow-rb-zenoh==0.0.9.
|
|
18
|
-
"rainbow-rb-flat-buffers==0.0.9.
|
|
19
|
-
"rainbow-rb-schemas==0.0.9.
|
|
20
|
-
"rainbow-rb-log==0.0.9.
|
|
16
|
+
"rainbow-rb-utils==0.0.9.dev18",
|
|
17
|
+
"rainbow-rb-zenoh==0.0.9.dev18",
|
|
18
|
+
"rainbow-rb-flat-buffers==0.0.9.dev18",
|
|
19
|
+
"rainbow-rb-schemas==0.0.9.dev18",
|
|
20
|
+
"rainbow-rb-log==0.0.9.dev18",
|
|
21
21
|
"rby1-sdk>=0.9.1",
|
|
22
22
|
]
|
|
23
23
|
|
|
@@ -30,4 +30,4 @@ where = ["src"]
|
|
|
30
30
|
include = ["rainbow.rb_sdk*"]
|
|
31
31
|
|
|
32
32
|
[tool.setuptools.package-data]
|
|
33
|
-
"*" = ["py.typed"]
|
|
33
|
+
"*" = ["py.typed", "*.pyi", "_core*.so", "_core*.pyd"]
|
{rainbow_rb_sdk-0.0.9.dev16 → rainbow_rb_sdk-0.0.9.dev18}/src/rainbow/rb_sdk/amr_sdk/amr_setting.py
RENAMED
|
@@ -9,6 +9,7 @@ from rainbow.rb_flat_buffers.SLAMNAV.RequestGetSensorInfo import RequestGetSenso
|
|
|
9
9
|
from rainbow.rb_flat_buffers.SLAMNAV.RequestGetSensorMode import RequestGetSensorModeT
|
|
10
10
|
from rainbow.rb_flat_buffers.SLAMNAV.RequestGetSettingCategory import RequestGetSettingCategoryT
|
|
11
11
|
from rainbow.rb_flat_buffers.SLAMNAV.RequestGetSettingParam import RequestGetSettingParamT
|
|
12
|
+
from rainbow.rb_flat_buffers.SLAMNAV.RequestRTSPSubscribe import RequestRTSPSubscribeT
|
|
12
13
|
from rainbow.rb_flat_buffers.SLAMNAV.RequestSetPduParam import RequestSetPduParamT
|
|
13
14
|
from rainbow.rb_flat_buffers.SLAMNAV.RequestSetRobotType import RequestSetRobotTypeT
|
|
14
15
|
from rainbow.rb_flat_buffers.SLAMNAV.RequestSetSensorInfo import RequestSetSensorInfoT
|
|
@@ -17,10 +18,12 @@ from rainbow.rb_flat_buffers.SLAMNAV.RequestSetSettingParam import RequestSetSet
|
|
|
17
18
|
from rainbow.rb_flat_buffers.SLAMNAV.ResponseGetDriveParam import ResponseGetDriveParamT
|
|
18
19
|
from rainbow.rb_flat_buffers.SLAMNAV.ResponseGetPduParam import ResponseGetPduParamT
|
|
19
20
|
from rainbow.rb_flat_buffers.SLAMNAV.ResponseGetRobotType import ResponseGetRobotTypeT
|
|
21
|
+
from rainbow.rb_flat_buffers.SLAMNAV.ResponseGetRTSPInfo import ResponseGetRTSPInfoT
|
|
20
22
|
from rainbow.rb_flat_buffers.SLAMNAV.ResponseGetSensorInfo import ResponseGetSensorInfoT
|
|
21
23
|
from rainbow.rb_flat_buffers.SLAMNAV.ResponseGetSensorMode import ResponseGetSensorModeT
|
|
22
24
|
from rainbow.rb_flat_buffers.SLAMNAV.ResponseGetSettingCategory import ResponseGetSettingCategoryT
|
|
23
25
|
from rainbow.rb_flat_buffers.SLAMNAV.ResponseGetSettingParam import ResponseGetSettingParamT
|
|
26
|
+
from rainbow.rb_flat_buffers.SLAMNAV.ResponseRTSPSubscribe import ResponseRTSPSubscribeT
|
|
24
27
|
from rainbow.rb_flat_buffers.SLAMNAV.ResponseSetPduParam import ResponseSetPduParamT
|
|
25
28
|
from rainbow.rb_flat_buffers.SLAMNAV.ResponseSetRobotType import ResponseSetRobotTypeT
|
|
26
29
|
from rainbow.rb_flat_buffers.SLAMNAV.ResponseSetSensorInfo import ResponseSetSensorInfoT
|
|
@@ -599,70 +602,43 @@ class RBAmrSettingSDK(RBBaseSDK):
|
|
|
599
602
|
|
|
600
603
|
return result.get("obj_payload")
|
|
601
604
|
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
# - cam_id: 카메라 ID (특정 카메라만 켜기 / 없으면 전부, switch가 off면 null)
|
|
643
|
-
# """
|
|
644
|
-
# if req_id is None:
|
|
645
|
-
# req_id = str(uuid.uuid4())
|
|
646
|
-
|
|
647
|
-
# # 1) RequestSetRTSPModeT 객체 생성
|
|
648
|
-
# req = RequestGetRTSPModeT()
|
|
649
|
-
# req.id = req_id
|
|
650
|
-
|
|
651
|
-
# # 2) 요청 전송
|
|
652
|
-
# result = self.zenoh_client.query_one(
|
|
653
|
-
# f"amr/{robot_model}/setting/getRTSPMode",
|
|
654
|
-
# flatbuffer_req_obj=req,
|
|
655
|
-
# flatbuffer_res_T_class=ResponseGetRTSPModeT,
|
|
656
|
-
# flatbuffer_buf_size=125,
|
|
657
|
-
# )
|
|
658
|
-
# # 3) 결과 처리 및 반환
|
|
659
|
-
# if result.get("obj_payload") is None:
|
|
660
|
-
# raise RuntimeError("Call Get RTSP Mode failed: obj_payload is None")
|
|
661
|
-
|
|
662
|
-
# if flow_manager_args is not None:
|
|
663
|
-
# if result["dict_payload"].get("result") == "accept":
|
|
664
|
-
# flow_manager_args.done()
|
|
665
|
-
# else:
|
|
666
|
-
# raise RuntimeError(result["dict_payload"].get("message"))
|
|
667
|
-
|
|
668
|
-
# return result.get("obj_payload")
|
|
605
|
+
def rtsp_subscribe(self, robot_model: str, cam_id: int, quality: str) -> ResponseRTSPSubscribeT:
|
|
606
|
+
"""
|
|
607
|
+
[RTSP 구독]
|
|
608
|
+
- robot_model: 로봇 모델
|
|
609
|
+
- cam_id: 카메라 ID
|
|
610
|
+
- quality: 비디오 품질
|
|
611
|
+
- ResponseRTSPSubscribeT 객체 반환
|
|
612
|
+
"""
|
|
613
|
+
req = RequestRTSPSubscribeT()
|
|
614
|
+
req.camId = cam_id
|
|
615
|
+
req.quality = quality
|
|
616
|
+
|
|
617
|
+
result = self.zenoh_client.query_one(
|
|
618
|
+
f"amr/{robot_model}/setting/rtsp/subscribe",
|
|
619
|
+
flatbuffer_req_obj=req,
|
|
620
|
+
flatbuffer_res_T_class=ResponseRTSPSubscribeT,
|
|
621
|
+
flatbuffer_buf_size=125,
|
|
622
|
+
)
|
|
623
|
+
|
|
624
|
+
if result.get("obj_payload") is None:
|
|
625
|
+
raise RuntimeError("Call RTSP Subscribe failed: obj_payload is None")
|
|
626
|
+
|
|
627
|
+
return result.get("obj_payload")
|
|
628
|
+
|
|
629
|
+
def get_rtsp_info(self, robot_model: str) -> ResponseGetRTSPInfoT:
|
|
630
|
+
"""
|
|
631
|
+
[RTSP 정보 조회]
|
|
632
|
+
- robot_model: 로봇 모델
|
|
633
|
+
- ResponseGetRTSPInfoT 객체 반환
|
|
634
|
+
"""
|
|
635
|
+
result = self.zenoh_client.query_one(
|
|
636
|
+
f"amr/{robot_model}/setting/rtsp/getInfo",
|
|
637
|
+
flatbuffer_res_T_class=ResponseGetRTSPInfoT,
|
|
638
|
+
flatbuffer_buf_size=125,
|
|
639
|
+
)
|
|
640
|
+
|
|
641
|
+
if result.get("obj_payload") is None:
|
|
642
|
+
raise RuntimeError("Call Get RTSP Info failed: obj_payload is None")
|
|
643
|
+
|
|
644
|
+
return result.get("obj_payload")
|
|
@@ -50,19 +50,27 @@ class RBBaseSDK:
|
|
|
50
50
|
# PID별 ZenohClient 인스턴스
|
|
51
51
|
_zenoh_clients: ClassVar[dict[int, ZenohClient]] = {}
|
|
52
52
|
|
|
53
|
-
|
|
53
|
+
# RLock: __new__ → _refresh_zenoh_client_for_pid 재진입 가능
|
|
54
|
+
_lock: ClassVar[threading.RLock] = threading.RLock()
|
|
54
55
|
|
|
55
56
|
@staticmethod
|
|
56
57
|
def _is_client_session_alive(client: ZenohClient | None) -> bool:
|
|
57
|
-
"""Zenoh 세션 객체의 기본 생존 상태를 점검한다.
|
|
58
|
+
"""Zenoh 세션 객체의 기본 생존 상태를 점검한다.
|
|
59
|
+
|
|
60
|
+
C++ 마이그레이션 후 ZenohClient는 ._core (ZenohClientCore) 를 보유한다.
|
|
61
|
+
close() 시 ._core 가 None 으로 설정되므로 그것을 생존 신호로 사용한다.
|
|
62
|
+
"""
|
|
58
63
|
if client is None:
|
|
59
64
|
return False
|
|
60
65
|
|
|
66
|
+
# C++ core 경로 (현재 구현)
|
|
67
|
+
if getattr(client, "_core", None) is not None:
|
|
68
|
+
return True
|
|
69
|
+
|
|
70
|
+
# 레거시 python-zenoh 경로 호환 (혹시 남아 있을 경우 대비)
|
|
61
71
|
session = getattr(client, "session", None)
|
|
62
72
|
if session is None:
|
|
63
73
|
return False
|
|
64
|
-
|
|
65
|
-
# zenoh 바인딩 버전에 따라 closed/is_closed 형태가 다를 수 있다.
|
|
66
74
|
for attr_name in ("is_closed", "closed"):
|
|
67
75
|
attr = getattr(session, attr_name, None)
|
|
68
76
|
if attr is None:
|
|
@@ -710,6 +718,17 @@ class RBBaseSDK:
|
|
|
710
718
|
)
|
|
711
719
|
|
|
712
720
|
print(f"[SDK] disconnected zenoh peer {peer_id}", flush=True)
|
|
721
|
+
|
|
722
|
+
# peer 해제 후 Zenoh 세션도 닫아 gossip/multihop 경로까지 완전히 차단
|
|
723
|
+
self._cleanup_resources()
|
|
724
|
+
pid = getattr(self, "_pid", None)
|
|
725
|
+
if pid is not None:
|
|
726
|
+
with RBBaseSDK._lock:
|
|
727
|
+
zenoh_client = RBBaseSDK._zenoh_clients.pop(pid, None)
|
|
728
|
+
if zenoh_client is not None:
|
|
729
|
+
with contextlib.suppress(Exception):
|
|
730
|
+
zenoh_client.close()
|
|
731
|
+
|
|
713
732
|
return True
|
|
714
733
|
|
|
715
734
|
async def _heartbeat_loop(self, peer_id: str, *, ttl: int, interval: float) -> None:
|