rainbow-rb-sdk 0.0.9.dev5__tar.gz → 0.0.9.dev6__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.
Files changed (73) hide show
  1. rainbow_rb_sdk-0.0.9.dev6/PKG-INFO +239 -0
  2. rainbow_rb_sdk-0.0.9.dev6/README.md +225 -0
  3. {rainbow_rb_sdk-0.0.9.dev5 → rainbow_rb_sdk-0.0.9.dev6}/pyproject.toml +8 -7
  4. {rainbow_rb_sdk-0.0.9.dev5 → rainbow_rb_sdk-0.0.9.dev6}/src/rainbow/rb_sdk/amr_sdk/amr_control.py +93 -3
  5. {rainbow_rb_sdk-0.0.9.dev5 → rainbow_rb_sdk-0.0.9.dev6}/src/rainbow/rb_sdk/amr_sdk/amr_file.py +5 -5
  6. {rainbow_rb_sdk-0.0.9.dev5 → rainbow_rb_sdk-0.0.9.dev6}/src/rainbow/rb_sdk/amr_sdk/amr_localization.py +2 -2
  7. {rainbow_rb_sdk-0.0.9.dev5 → rainbow_rb_sdk-0.0.9.dev6}/src/rainbow/rb_sdk/amr_sdk/amr_map.py +7 -6
  8. {rainbow_rb_sdk-0.0.9.dev5 → rainbow_rb_sdk-0.0.9.dev6}/src/rainbow/rb_sdk/amr_sdk/amr_move.py +2 -2
  9. {rainbow_rb_sdk-0.0.9.dev5 → rainbow_rb_sdk-0.0.9.dev6}/src/rainbow/rb_sdk/amr_sdk/amr_program.py +1 -3
  10. {rainbow_rb_sdk-0.0.9.dev5 → rainbow_rb_sdk-0.0.9.dev6}/src/rainbow/rb_sdk/amr_sdk/amr_setting.py +68 -0
  11. {rainbow_rb_sdk-0.0.9.dev5 → rainbow_rb_sdk-0.0.9.dev6}/src/rainbow/rb_sdk/base.py +259 -8
  12. {rainbow_rb_sdk-0.0.9.dev5 → rainbow_rb_sdk-0.0.9.dev6}/src/rainbow/rb_sdk/manipulate.py +6 -1
  13. {rainbow_rb_sdk-0.0.9.dev5 → rainbow_rb_sdk-0.0.9.dev6}/src/rainbow/rb_sdk/manipulate_sdk/manipulate_config.py +290 -20
  14. {rainbow_rb_sdk-0.0.9.dev5 → rainbow_rb_sdk-0.0.9.dev6}/src/rainbow/rb_sdk/manipulate_sdk/manipulate_get_data.py +4 -9
  15. {rainbow_rb_sdk-0.0.9.dev5 → rainbow_rb_sdk-0.0.9.dev6}/src/rainbow/rb_sdk/manipulate_sdk/manipulate_io.py +15 -7
  16. rainbow_rb_sdk-0.0.9.dev6/src/rainbow/rb_sdk/manipulate_sdk/manipulate_maintenance.py +535 -0
  17. {rainbow_rb_sdk-0.0.9.dev5 → rainbow_rb_sdk-0.0.9.dev6}/src/rainbow/rb_sdk/manipulate_sdk/manipulate_move.py +782 -134
  18. {rainbow_rb_sdk-0.0.9.dev5 → rainbow_rb_sdk-0.0.9.dev6}/src/rainbow/rb_sdk/manipulate_sdk/manipulate_program.py +146 -66
  19. rainbow_rb_sdk-0.0.9.dev6/src/rainbow/rb_sdk/manipulate_sdk/manipulate_service.py +1503 -0
  20. rainbow_rb_sdk-0.0.9.dev6/src/rainbow/rb_sdk/program_sdk/client_modules.pyi +371 -0
  21. {rainbow_rb_sdk-0.0.9.dev5 → rainbow_rb_sdk-0.0.9.dev6}/src/rainbow/rb_sdk/program_sdk/program.py +95 -194
  22. rainbow_rb_sdk-0.0.9.dev6/src/rainbow/rb_sdk/program_sdk/program_interface.py +646 -0
  23. rainbow_rb_sdk-0.0.9.dev6/src/rainbow/rb_sdk/program_sdk/test_binding.py +243 -0
  24. rainbow_rb_sdk-0.0.9.dev6/src/rainbow/rb_sdk/rby1.py +58 -0
  25. {rainbow_rb_sdk-0.0.9.dev5 → rainbow_rb_sdk-0.0.9.dev6}/src/rainbow/rb_sdk/rby1_sdk/__init__.py +1 -6
  26. rainbow_rb_sdk-0.0.9.dev6/src/rainbow/rb_sdk/rby1_sdk/base.py +165 -0
  27. rainbow_rb_sdk-0.0.9.dev6/src/rainbow/rb_sdk/rby1_sdk/client.py +70 -0
  28. rainbow_rb_sdk-0.0.9.dev6/src/rainbow/rb_sdk/rby1_sdk/config.py +24 -0
  29. rainbow_rb_sdk-0.0.9.dev6/src/rainbow/rb_sdk/rby1_sdk/control.py +169 -0
  30. {rainbow_rb_sdk-0.0.9.dev5 → rainbow_rb_sdk-0.0.9.dev6}/src/rainbow/rb_sdk/rby1_sdk/exceptions.py +0 -4
  31. rainbow_rb_sdk-0.0.9.dev6/src/rainbow/rb_sdk/rby1_sdk/state.py +80 -0
  32. rainbow_rb_sdk-0.0.9.dev6/src/rainbow/rb_sdk/schema/program_schema.py +83 -0
  33. rainbow_rb_sdk-0.0.9.dev6/src/rainbow_rb_sdk.egg-info/PKG-INFO +239 -0
  34. {rainbow_rb_sdk-0.0.9.dev5 → rainbow_rb_sdk-0.0.9.dev6}/src/rainbow_rb_sdk.egg-info/SOURCES.txt +4 -1
  35. rainbow_rb_sdk-0.0.9.dev6/src/rainbow_rb_sdk.egg-info/requires.txt +6 -0
  36. rainbow_rb_sdk-0.0.9.dev5/PKG-INFO +0 -137
  37. rainbow_rb_sdk-0.0.9.dev5/README.md +0 -124
  38. rainbow_rb_sdk-0.0.9.dev5/src/rainbow/rb_sdk/manipulate_sdk/manipulate_service.py +0 -761
  39. rainbow_rb_sdk-0.0.9.dev5/src/rainbow/rb_sdk/manipulate_sdk/manipulate_smbc.py +0 -144
  40. rainbow_rb_sdk-0.0.9.dev5/src/rainbow/rb_sdk/rby1.py +0 -18
  41. rainbow_rb_sdk-0.0.9.dev5/src/rainbow/rb_sdk/rby1_sdk/base.py +0 -8
  42. rainbow_rb_sdk-0.0.9.dev5/src/rainbow/rb_sdk/rby1_sdk/client.py +0 -111
  43. rainbow_rb_sdk-0.0.9.dev5/src/rainbow/rb_sdk/rby1_sdk/config.py +0 -9
  44. rainbow_rb_sdk-0.0.9.dev5/src/rainbow/rb_sdk/rby1_sdk/control.py +0 -64
  45. rainbow_rb_sdk-0.0.9.dev5/src/rainbow/rb_sdk/rby1_sdk/state.py +0 -40
  46. rainbow_rb_sdk-0.0.9.dev5/src/rainbow/rb_sdk/schema/program_schema.py +0 -51
  47. rainbow_rb_sdk-0.0.9.dev5/src/rainbow_rb_sdk.egg-info/PKG-INFO +0 -137
  48. rainbow_rb_sdk-0.0.9.dev5/src/rainbow_rb_sdk.egg-info/requires.txt +0 -5
  49. {rainbow_rb_sdk-0.0.9.dev5 → rainbow_rb_sdk-0.0.9.dev6}/setup.cfg +0 -0
  50. {rainbow_rb_sdk-0.0.9.dev5 → rainbow_rb_sdk-0.0.9.dev6}/src/rainbow/rb_sdk/__init__.py +0 -0
  51. {rainbow_rb_sdk-0.0.9.dev5 → rainbow_rb_sdk-0.0.9.dev6}/src/rainbow/rb_sdk/amr.py +0 -0
  52. {rainbow_rb_sdk-0.0.9.dev5 → rainbow_rb_sdk-0.0.9.dev6}/src/rainbow/rb_sdk/amr_sdk/__init__.py +0 -0
  53. {rainbow_rb_sdk-0.0.9.dev5 → rainbow_rb_sdk-0.0.9.dev6}/src/rainbow/rb_sdk/amr_sdk/amr_accessory.py +0 -0
  54. {rainbow_rb_sdk-0.0.9.dev5 → rainbow_rb_sdk-0.0.9.dev6}/src/rainbow/rb_sdk/amr_sdk/amr_capability.py +0 -0
  55. {rainbow_rb_sdk-0.0.9.dev5 → rainbow_rb_sdk-0.0.9.dev6}/src/rainbow/rb_sdk/amr_sdk/amr_status.py +0 -0
  56. {rainbow_rb_sdk-0.0.9.dev5 → rainbow_rb_sdk-0.0.9.dev6}/src/rainbow/rb_sdk/amr_sdk/schema/__init__.py +0 -0
  57. {rainbow_rb_sdk-0.0.9.dev5 → rainbow_rb_sdk-0.0.9.dev6}/src/rainbow/rb_sdk/base_sdk/__init__.py +0 -0
  58. {rainbow_rb_sdk-0.0.9.dev5 → rainbow_rb_sdk-0.0.9.dev6}/src/rainbow/rb_sdk/base_sdk/base_schema.py +0 -0
  59. {rainbow_rb_sdk-0.0.9.dev5 → rainbow_rb_sdk-0.0.9.dev6}/src/rainbow/rb_sdk/manipulate_sdk/__init__.py +0 -0
  60. {rainbow_rb_sdk-0.0.9.dev5 → rainbow_rb_sdk-0.0.9.dev6}/src/rainbow/rb_sdk/manipulate_sdk/manipulate_point.py +0 -0
  61. {rainbow_rb_sdk-0.0.9.dev5 → rainbow_rb_sdk-0.0.9.dev6}/src/rainbow/rb_sdk/manipulate_sdk/manipulate_state.py +0 -0
  62. {rainbow_rb_sdk-0.0.9.dev5 → rainbow_rb_sdk-0.0.9.dev6}/src/rainbow/rb_sdk/manipulate_sdk/schema/__init__.py +0 -0
  63. {rainbow_rb_sdk-0.0.9.dev5 → rainbow_rb_sdk-0.0.9.dev6}/src/rainbow/rb_sdk/manipulate_sdk/schema/manipulate_config_schema.py +0 -0
  64. {rainbow_rb_sdk-0.0.9.dev5 → rainbow_rb_sdk-0.0.9.dev6}/src/rainbow/rb_sdk/manipulate_sdk/schema/manipulate_io_schema.py +0 -0
  65. {rainbow_rb_sdk-0.0.9.dev5 → rainbow_rb_sdk-0.0.9.dev6}/src/rainbow/rb_sdk/manipulate_sdk/schema/manipulate_move_schema.py +0 -0
  66. {rainbow_rb_sdk-0.0.9.dev5 → rainbow_rb_sdk-0.0.9.dev6}/src/rainbow/rb_sdk/manipulate_sdk/schema/manipulate_program_schema.py +0 -0
  67. {rainbow_rb_sdk-0.0.9.dev5 → rainbow_rb_sdk-0.0.9.dev6}/src/rainbow/rb_sdk/program_sdk/__init__.py +0 -0
  68. {rainbow_rb_sdk-0.0.9.dev5 → rainbow_rb_sdk-0.0.9.dev6}/src/rainbow/rb_sdk/schema/__init__.py +0 -0
  69. {rainbow_rb_sdk-0.0.9.dev5 → rainbow_rb_sdk-0.0.9.dev6}/src/rainbow/rb_sdk/schema/amr_schema.py +0 -0
  70. {rainbow_rb_sdk-0.0.9.dev5 → rainbow_rb_sdk-0.0.9.dev6}/src/rainbow/rb_sdk/schema/base_schema.py +0 -0
  71. {rainbow_rb_sdk-0.0.9.dev5 → rainbow_rb_sdk-0.0.9.dev6}/src/rainbow/rb_sdk/schema/manipulate_schema.py +0 -0
  72. {rainbow_rb_sdk-0.0.9.dev5 → rainbow_rb_sdk-0.0.9.dev6}/src/rainbow_rb_sdk.egg-info/dependency_links.txt +0 -0
  73. {rainbow_rb_sdk-0.0.9.dev5 → rainbow_rb_sdk-0.0.9.dev6}/src/rainbow_rb_sdk.egg-info/top_level.txt +0 -0
@@ -0,0 +1,239 @@
1
+ Metadata-Version: 2.4
2
+ Name: rainbow-rb-sdk
3
+ Version: 0.0.9.dev6
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.dev6
9
+ Requires-Dist: rainbow-rb-zenoh==0.0.9.dev6
10
+ Requires-Dist: rainbow-rb-flat-buffers==0.0.9.dev6
11
+ Requires-Dist: rainbow-rb-schemas==0.0.9.dev6
12
+ Requires-Dist: rainbow-rb-log==0.0.9.dev6
13
+ Requires-Dist: rby1-sdk>=0.9.1
14
+
15
+ # rb_sdk
16
+
17
+ Rainbow Robotics 통합 Python SDK. AMR · Manipulator · RB-Y1 휴머노이드 제어와 Rainbow Robot Service(common) 연동을 단일 API로 제공합니다.
18
+
19
+ ## 진입점
20
+
21
+ | 클래스 | 용도 |
22
+ |---|---|
23
+ | `RBAmrSDK` | AMR(자율 주행) 로봇 제어 |
24
+ | `RBManipulateSDK` | 협동 로봇 매니퓰레이터 제어 |
25
+ | `RBRby1SDK` | RB-Y1 휴머노이드 제어 |
26
+ | `RBBaseSDK` | 공통 베이스 (직접 상속하지 않는 한 사용할 일 없음) |
27
+
28
+ 내부적으로 Zenoh pub/sub/query 메시 위에서 동작하며, 같은 PC(로봇 본체)에서 실행할 때는 별도 설정 없이 즉시 사용 가능합니다.
29
+
30
+ ---
31
+
32
+ ## 1. 설치
33
+
34
+ ### 워크스페이스(rby2 모노레포 내부)
35
+
36
+ ```bash
37
+ cd /path/to/rby2/backend
38
+ uv add rb_sdk --package your_package
39
+ ```
40
+
41
+ ### PyPI 설치
42
+
43
+ ```bash
44
+ pip install rb_sdk
45
+ # RB-Y1 휴머노이드 제어가 필요하면 함께 설치
46
+ pip install rby1-sdk
47
+ ```
48
+
49
+ `requires-python = ">=3.12,<3.13"` — Python 3.12 전용.
50
+
51
+ ---
52
+
53
+ ## 2. 기본 사용 (로봇 본체에서 실행하는 경우)
54
+
55
+ `common` 서비스와 같은 PC에서 실행되는 스크립트라면 추가 설정 없이 그대로 사용 가능합니다.
56
+
57
+ ```python
58
+ from rb_sdk import RBAmrSDK, RBManipulateSDK
59
+
60
+ amr = RBAmrSDK()
61
+ manipulate = RBManipulateSDK()
62
+
63
+ # 이 시점에 ZenohClient가 127.0.0.1:7447(common)에 자동 연결
64
+ manipulate.move.call_move_j(
65
+ robot_model="C500920",
66
+ target={"tar_values": [0, 0, 0, 0, 0, 0], "tar_frame": 0, "tar_unit": 0},
67
+ )
68
+ ```
69
+
70
+ `rb_sdk`는 lazy import 지원: `from rb_sdk import ...` 한 줄로 가져옵니다.
71
+
72
+ ---
73
+
74
+ ## 3. 외부 PC에서 사용 (Remote Connect)
75
+
76
+ 개발용 노트북, 태블릿 등 **로봇 본체와 다른 머신**에서 SDK를 사용하는 경우, 두 가지를 함께 해야 합니다.
77
+
78
+ ### 3-1. Zenoh 메시 연결 (필수)
79
+
80
+ ZenohClient가 remote common에 붙도록 환경변수 설정:
81
+
82
+ ```bash
83
+ export ZENOH_PEER_CONNECT_ENDPOINTS=tcp/<common_host_ip>:7447
84
+ python my_script.py
85
+ ```
86
+
87
+ ### 3-2. common 측 peer 등록 (권장) — `sdk.connect()`
88
+
89
+ 서버에서 외부 peer를 추적하고 끊김 감지가 필요하면 SDK의 `connect()`를 호출합니다.
90
+
91
+ ```python
92
+ import asyncio
93
+ from rb_sdk import RBManipulateSDK
94
+
95
+ async def main():
96
+ sdk = RBManipulateSDK()
97
+
98
+ # common 서비스에 peer 등록 + 자동 heartbeat 시작
99
+ peer_id = await sdk.connect(
100
+ token="<JWT 토큰>", # common 서비스 인증 토큰
101
+ host="192.168.1.100", # common이 떠 있는 PC IP
102
+ ttl=30, # 서버 측 세션 TTL(초). heartbeat 끊기면 자동 해제
103
+ # zenoh_port=None, # None → OS가 빈 포트 자동 배정 (충돌 없음)
104
+ # heartbeat_interval=15.0, # 기본: ttl / 2
105
+ )
106
+
107
+ # ... SDK 호출 ...
108
+ sdk.move.call_move_j(robot_model="C500920", target={...})
109
+
110
+ await sdk.disconnect()
111
+
112
+ asyncio.run(main())
113
+ ```
114
+
115
+ #### 주요 특징
116
+
117
+ - **로컬 IP 자동 감지**: `host` 방향의 라우팅 인터페이스 IP를 자동으로 찾아 common에 알림
118
+ - **포트 자동 배정**: 별도 지정 없이 OS가 빈 포트를 잡아주므로 포트 충돌 없음
119
+ - **자동 heartbeat**: 주기적으로 TTL 연장. 스크립트 종료 / 크래시 시 TTL 만료로 서버 측 정리
120
+ - **같은 PC 자동 감지**: `host`가 localhost거나 자기 IP인 경우 `connect()`는 아무것도 하지 않고 `None` 반환 (이미 메시 안에 있음)
121
+
122
+ #### connect() 인자
123
+
124
+ | 인자 | 타입 | 기본 | 설명 |
125
+ |---|---|---|---|
126
+ | `token` | `str` | (필수) | common 서비스 JWT |
127
+ | `host` | `str` | (필수) | common이 실행 중인 PC IP |
128
+ | `common_port` | `int` | `8000` | common HTTP 포트 |
129
+ | `zenoh_port` | `int \| None` | `None` | 로컬 Zenoh listen 포트. `None`이면 자동 |
130
+ | `ttl` | `int` | `30` | 서버 측 세션 TTL(초) |
131
+ | `heartbeat_interval` | `float \| None` | `None` | heartbeat 주기. `None`이면 `ttl/2` |
132
+
133
+ ---
134
+
135
+ ## 4. AMR SDK (`RBAmrSDK`)
136
+
137
+ ```python
138
+ from rb_sdk import RBAmrSDK
139
+
140
+ sdk = RBAmrSDK()
141
+ ```
142
+
143
+ | 하위 모듈 | 기능 |
144
+ |---|---|
145
+ | `move` | 이동 명령(`move_to`, `move_jog` 등) |
146
+ | `control` | 전원/긴급정지/잠금 등 |
147
+ | `localization` | 위치 추정 |
148
+ | `map` | 맵 로드/저장 |
149
+ | `setting` | 환경설정 |
150
+ | `file` | 맵/리소스 파일 관리 |
151
+ | `status` | 상태 조회 |
152
+
153
+ ---
154
+
155
+ ## 5. Manipulate SDK (`RBManipulateSDK`)
156
+
157
+ ```python
158
+ from rb_sdk import RBManipulateSDK
159
+
160
+ sdk = RBManipulateSDK()
161
+ ```
162
+
163
+ | 하위 모듈 | 기능 |
164
+ |---|---|
165
+ | `program` | 프로그램 실행/제어 |
166
+ | `move` | `call_move_j`, `call_move_l`, `call_move_jb_*` 등 |
167
+ | `config` | 환경설정/파라미터 |
168
+ | `io` | DIO/AIO 제어 |
169
+ | `get_data` | 상태·좌표 조회 |
170
+ | `point` | 포인트/좌표 등록 |
171
+ | `service` | 미니 탭 기능 |
172
+ | `maintenance` | 관리자 설정 |
173
+ | `state` | 실시간 상태 구독 |
174
+
175
+ ---
176
+
177
+ ## 6. RB-Y1 SDK (`RBRby1SDK`)
178
+
179
+ 공식 `rby1-sdk` 래퍼.
180
+
181
+ ```python
182
+ from rb_sdk import RBRby1SDK
183
+
184
+ sdk = RBRby1SDK(endpoint="192.168.30.1:50051", model=None, auto_connect=True)
185
+
186
+ print(sdk.connected)
187
+ print(sdk.whoami())
188
+
189
+ sdk.control.power_on()
190
+ sdk.control.servo_on()
191
+
192
+ state = sdk.state.get_state()
193
+ print(state)
194
+
195
+ sdk.disconnect()
196
+ ```
197
+
198
+ > ⚠️ `RBRby1SDK.connect()` / `disconnect()`는 RB-Y1 gRPC endpoint 전용 메서드로, `RBBaseSDK.connect()`(common HTTP 등록)와 별개입니다. 자세한 차이는 클래스 docstring 참조.
199
+
200
+ 지원 메서드:
201
+
202
+ - 공통: `connect()`, `disconnect()`, `whoami()`, `call(method, *args, **kwargs)`
203
+ - 제어: `control.invoke(...)`, `control.power_on()`, `control.servo_on()`
204
+ - 상태: `state.get_state()`
205
+
206
+ ---
207
+
208
+ ## 7. Flow Manager (PyFM) 연동
209
+
210
+ 여러 SDK 메서드는 `flow_manager_args`를 받아 Step 실행 완료 시 `done()` 콜백을 호출합니다.
211
+
212
+ ```python
213
+ from rb_schemas.sdk import FlowManagerArgs
214
+ from rb_sdk import RBManipulateSDK
215
+
216
+ sdk = RBManipulateSDK()
217
+
218
+ def step_func(flow_manager_args: FlowManagerArgs | None = None):
219
+ sdk.move.call_move_j(
220
+ robot_model="C500920",
221
+ target={"tar_values": [0]*6, "tar_frame": 0, "tar_unit": 0},
222
+ flow_manager_args=flow_manager_args,
223
+ )
224
+ ```
225
+
226
+ ---
227
+
228
+ ## 8. 주의사항
229
+
230
+ - `RBBaseSDK`는 프로세스 단위 싱글톤 + 공유 ZenohClient 구조입니다. 같은 프로세스에서 여러 번 `RBManipulateSDK()`를 호출해도 동일 인스턴스가 반환됩니다.
231
+ - `RBRby1SDK`는 최초 `endpoint/model` 기준으로 세션이 공유됩니다.
232
+ - 연결 대상(zenoh, rby1 endpoint, common HTTP)이 준비되지 않으면 런타임 예외가 발생합니다.
233
+ - 외부 PC에서 SDK 사용 시 **방화벽이 7447/TCP(zenoh)와 8000/TCP(common HTTP)을 양방향으로 허용**해야 합니다.
234
+
235
+ ---
236
+
237
+ ## 9. 라이선스 / 문의
238
+
239
+ © Rainbow Robotics. 내부 이슈/문의: [GitHub Issues](https://github.com/rainbowrobotics/rby2/issues)
@@ -0,0 +1,225 @@
1
+ # rb_sdk
2
+
3
+ Rainbow Robotics 통합 Python SDK. AMR · Manipulator · RB-Y1 휴머노이드 제어와 Rainbow Robot Service(common) 연동을 단일 API로 제공합니다.
4
+
5
+ ## 진입점
6
+
7
+ | 클래스 | 용도 |
8
+ |---|---|
9
+ | `RBAmrSDK` | AMR(자율 주행) 로봇 제어 |
10
+ | `RBManipulateSDK` | 협동 로봇 매니퓰레이터 제어 |
11
+ | `RBRby1SDK` | RB-Y1 휴머노이드 제어 |
12
+ | `RBBaseSDK` | 공통 베이스 (직접 상속하지 않는 한 사용할 일 없음) |
13
+
14
+ 내부적으로 Zenoh pub/sub/query 메시 위에서 동작하며, 같은 PC(로봇 본체)에서 실행할 때는 별도 설정 없이 즉시 사용 가능합니다.
15
+
16
+ ---
17
+
18
+ ## 1. 설치
19
+
20
+ ### 워크스페이스(rby2 모노레포 내부)
21
+
22
+ ```bash
23
+ cd /path/to/rby2/backend
24
+ uv add rb_sdk --package your_package
25
+ ```
26
+
27
+ ### PyPI 설치
28
+
29
+ ```bash
30
+ pip install rb_sdk
31
+ # RB-Y1 휴머노이드 제어가 필요하면 함께 설치
32
+ pip install rby1-sdk
33
+ ```
34
+
35
+ `requires-python = ">=3.12,<3.13"` — Python 3.12 전용.
36
+
37
+ ---
38
+
39
+ ## 2. 기본 사용 (로봇 본체에서 실행하는 경우)
40
+
41
+ `common` 서비스와 같은 PC에서 실행되는 스크립트라면 추가 설정 없이 그대로 사용 가능합니다.
42
+
43
+ ```python
44
+ from rb_sdk import RBAmrSDK, RBManipulateSDK
45
+
46
+ amr = RBAmrSDK()
47
+ manipulate = RBManipulateSDK()
48
+
49
+ # 이 시점에 ZenohClient가 127.0.0.1:7447(common)에 자동 연결
50
+ manipulate.move.call_move_j(
51
+ robot_model="C500920",
52
+ target={"tar_values": [0, 0, 0, 0, 0, 0], "tar_frame": 0, "tar_unit": 0},
53
+ )
54
+ ```
55
+
56
+ `rb_sdk`는 lazy import 지원: `from rb_sdk import ...` 한 줄로 가져옵니다.
57
+
58
+ ---
59
+
60
+ ## 3. 외부 PC에서 사용 (Remote Connect)
61
+
62
+ 개발용 노트북, 태블릿 등 **로봇 본체와 다른 머신**에서 SDK를 사용하는 경우, 두 가지를 함께 해야 합니다.
63
+
64
+ ### 3-1. Zenoh 메시 연결 (필수)
65
+
66
+ ZenohClient가 remote common에 붙도록 환경변수 설정:
67
+
68
+ ```bash
69
+ export ZENOH_PEER_CONNECT_ENDPOINTS=tcp/<common_host_ip>:7447
70
+ python my_script.py
71
+ ```
72
+
73
+ ### 3-2. common 측 peer 등록 (권장) — `sdk.connect()`
74
+
75
+ 서버에서 외부 peer를 추적하고 끊김 감지가 필요하면 SDK의 `connect()`를 호출합니다.
76
+
77
+ ```python
78
+ import asyncio
79
+ from rb_sdk import RBManipulateSDK
80
+
81
+ async def main():
82
+ sdk = RBManipulateSDK()
83
+
84
+ # common 서비스에 peer 등록 + 자동 heartbeat 시작
85
+ peer_id = await sdk.connect(
86
+ token="<JWT 토큰>", # common 서비스 인증 토큰
87
+ host="192.168.1.100", # common이 떠 있는 PC IP
88
+ ttl=30, # 서버 측 세션 TTL(초). heartbeat 끊기면 자동 해제
89
+ # zenoh_port=None, # None → OS가 빈 포트 자동 배정 (충돌 없음)
90
+ # heartbeat_interval=15.0, # 기본: ttl / 2
91
+ )
92
+
93
+ # ... SDK 호출 ...
94
+ sdk.move.call_move_j(robot_model="C500920", target={...})
95
+
96
+ await sdk.disconnect()
97
+
98
+ asyncio.run(main())
99
+ ```
100
+
101
+ #### 주요 특징
102
+
103
+ - **로컬 IP 자동 감지**: `host` 방향의 라우팅 인터페이스 IP를 자동으로 찾아 common에 알림
104
+ - **포트 자동 배정**: 별도 지정 없이 OS가 빈 포트를 잡아주므로 포트 충돌 없음
105
+ - **자동 heartbeat**: 주기적으로 TTL 연장. 스크립트 종료 / 크래시 시 TTL 만료로 서버 측 정리
106
+ - **같은 PC 자동 감지**: `host`가 localhost거나 자기 IP인 경우 `connect()`는 아무것도 하지 않고 `None` 반환 (이미 메시 안에 있음)
107
+
108
+ #### connect() 인자
109
+
110
+ | 인자 | 타입 | 기본 | 설명 |
111
+ |---|---|---|---|
112
+ | `token` | `str` | (필수) | common 서비스 JWT |
113
+ | `host` | `str` | (필수) | common이 실행 중인 PC IP |
114
+ | `common_port` | `int` | `8000` | common HTTP 포트 |
115
+ | `zenoh_port` | `int \| None` | `None` | 로컬 Zenoh listen 포트. `None`이면 자동 |
116
+ | `ttl` | `int` | `30` | 서버 측 세션 TTL(초) |
117
+ | `heartbeat_interval` | `float \| None` | `None` | heartbeat 주기. `None`이면 `ttl/2` |
118
+
119
+ ---
120
+
121
+ ## 4. AMR SDK (`RBAmrSDK`)
122
+
123
+ ```python
124
+ from rb_sdk import RBAmrSDK
125
+
126
+ sdk = RBAmrSDK()
127
+ ```
128
+
129
+ | 하위 모듈 | 기능 |
130
+ |---|---|
131
+ | `move` | 이동 명령(`move_to`, `move_jog` 등) |
132
+ | `control` | 전원/긴급정지/잠금 등 |
133
+ | `localization` | 위치 추정 |
134
+ | `map` | 맵 로드/저장 |
135
+ | `setting` | 환경설정 |
136
+ | `file` | 맵/리소스 파일 관리 |
137
+ | `status` | 상태 조회 |
138
+
139
+ ---
140
+
141
+ ## 5. Manipulate SDK (`RBManipulateSDK`)
142
+
143
+ ```python
144
+ from rb_sdk import RBManipulateSDK
145
+
146
+ sdk = RBManipulateSDK()
147
+ ```
148
+
149
+ | 하위 모듈 | 기능 |
150
+ |---|---|
151
+ | `program` | 프로그램 실행/제어 |
152
+ | `move` | `call_move_j`, `call_move_l`, `call_move_jb_*` 등 |
153
+ | `config` | 환경설정/파라미터 |
154
+ | `io` | DIO/AIO 제어 |
155
+ | `get_data` | 상태·좌표 조회 |
156
+ | `point` | 포인트/좌표 등록 |
157
+ | `service` | 미니 탭 기능 |
158
+ | `maintenance` | 관리자 설정 |
159
+ | `state` | 실시간 상태 구독 |
160
+
161
+ ---
162
+
163
+ ## 6. RB-Y1 SDK (`RBRby1SDK`)
164
+
165
+ 공식 `rby1-sdk` 래퍼.
166
+
167
+ ```python
168
+ from rb_sdk import RBRby1SDK
169
+
170
+ sdk = RBRby1SDK(endpoint="192.168.30.1:50051", model=None, auto_connect=True)
171
+
172
+ print(sdk.connected)
173
+ print(sdk.whoami())
174
+
175
+ sdk.control.power_on()
176
+ sdk.control.servo_on()
177
+
178
+ state = sdk.state.get_state()
179
+ print(state)
180
+
181
+ sdk.disconnect()
182
+ ```
183
+
184
+ > ⚠️ `RBRby1SDK.connect()` / `disconnect()`는 RB-Y1 gRPC endpoint 전용 메서드로, `RBBaseSDK.connect()`(common HTTP 등록)와 별개입니다. 자세한 차이는 클래스 docstring 참조.
185
+
186
+ 지원 메서드:
187
+
188
+ - 공통: `connect()`, `disconnect()`, `whoami()`, `call(method, *args, **kwargs)`
189
+ - 제어: `control.invoke(...)`, `control.power_on()`, `control.servo_on()`
190
+ - 상태: `state.get_state()`
191
+
192
+ ---
193
+
194
+ ## 7. Flow Manager (PyFM) 연동
195
+
196
+ 여러 SDK 메서드는 `flow_manager_args`를 받아 Step 실행 완료 시 `done()` 콜백을 호출합니다.
197
+
198
+ ```python
199
+ from rb_schemas.sdk import FlowManagerArgs
200
+ from rb_sdk import RBManipulateSDK
201
+
202
+ sdk = RBManipulateSDK()
203
+
204
+ def step_func(flow_manager_args: FlowManagerArgs | None = None):
205
+ sdk.move.call_move_j(
206
+ robot_model="C500920",
207
+ target={"tar_values": [0]*6, "tar_frame": 0, "tar_unit": 0},
208
+ flow_manager_args=flow_manager_args,
209
+ )
210
+ ```
211
+
212
+ ---
213
+
214
+ ## 8. 주의사항
215
+
216
+ - `RBBaseSDK`는 프로세스 단위 싱글톤 + 공유 ZenohClient 구조입니다. 같은 프로세스에서 여러 번 `RBManipulateSDK()`를 호출해도 동일 인스턴스가 반환됩니다.
217
+ - `RBRby1SDK`는 최초 `endpoint/model` 기준으로 세션이 공유됩니다.
218
+ - 연결 대상(zenoh, rby1 endpoint, common HTTP)이 준비되지 않으면 런타임 예외가 발생합니다.
219
+ - 외부 PC에서 SDK 사용 시 **방화벽이 7447/TCP(zenoh)와 8000/TCP(common HTTP)을 양방향으로 허용**해야 합니다.
220
+
221
+ ---
222
+
223
+ ## 9. 라이선스 / 문의
224
+
225
+ © Rainbow Robotics. 내부 이슈/문의: [GitHub Issues](https://github.com/rainbowrobotics/rby2/issues)
@@ -4,20 +4,21 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "rainbow-rb-sdk"
7
- version = "0.0.9.dev5"
7
+ version = "0.0.9.dev6"
8
8
  requires-python = ">=3.12,<3.13"
9
- description = "Rainbow Python SDK"
9
+ description = "Rainbow Robotics 통합 Python SDK — AMR, 매니퓰레이터, RB-Y1 휴머노이드와 Rainbow Robot Service(common) 연동"
10
10
  authors = [
11
11
  { name = "Derek", email = "dfd1123@rainbow-robotics.com" },
12
12
  ]
13
13
  readme = "README.md"
14
14
 
15
15
  dependencies = [
16
- "rainbow-rb-utils==0.0.9.dev5",
17
- "rainbow-rb-zenoh==0.0.9.dev5",
18
- "rainbow-rb-flat-buffers==0.0.9.dev5",
19
- "rainbow-rb-schemas==0.0.9.dev5",
20
- "rainbow-rb-log==0.0.9.dev5",
16
+ "rainbow-rb-utils==0.0.9.dev6",
17
+ "rainbow-rb-zenoh==0.0.9.dev6",
18
+ "rainbow-rb-flat-buffers==0.0.9.dev6",
19
+ "rainbow-rb-schemas==0.0.9.dev6",
20
+ "rainbow-rb-log==0.0.9.dev6",
21
+ "rby1-sdk>=0.9.1",
21
22
  ]
22
23
 
23
24
  [tool.setuptools]
@@ -13,6 +13,8 @@ from rainbow.rb_flat_buffers.SLAMNAV.RequestGetObsBox import RequestGetObsBoxT
13
13
  from rainbow.rb_flat_buffers.SLAMNAV.RequestGetSafetyField import RequestGetSafetyFieldT
14
14
  from rainbow.rb_flat_buffers.SLAMNAV.RequestGetSafetyFlag import RequestGetSafetyFlagT
15
15
  from rainbow.rb_flat_buffers.SLAMNAV.RequestGetSafetyIo import RequestGetSafetyIoT
16
+ from rainbow.rb_flat_buffers.SLAMNAV.RequestSetAvoid import RequestSetAvoidT
17
+ from rainbow.rb_flat_buffers.SLAMNAV.RequestSetDetectMode import RequestSetDetectModeT
16
18
  from rainbow.rb_flat_buffers.SLAMNAV.RequestSetJog import RequestSetJogT
17
19
  from rainbow.rb_flat_buffers.SLAMNAV.RequestSetLed import RequestSetLedT
18
20
  from rainbow.rb_flat_buffers.SLAMNAV.RequestSetMotor import RequestSetMotorT
@@ -29,6 +31,8 @@ from rainbow.rb_flat_buffers.SLAMNAV.ResponseGetObsBox import ResponseGetObsBoxT
29
31
  from rainbow.rb_flat_buffers.SLAMNAV.ResponseGetSafetyField import ResponseGetSafetyFieldT
30
32
  from rainbow.rb_flat_buffers.SLAMNAV.ResponseGetSafetyFlag import ResponseGetSafetyFlagT
31
33
  from rainbow.rb_flat_buffers.SLAMNAV.ResponseGetSafetyIo import ResponseGetSafetyIoT
34
+ from rainbow.rb_flat_buffers.SLAMNAV.ResponseSetAvoid import ResponseSetAvoidT
35
+ from rainbow.rb_flat_buffers.SLAMNAV.ResponseSetDetectMode import ResponseSetDetectModeT
32
36
  from rainbow.rb_flat_buffers.SLAMNAV.ResponseSetJog import ResponseSetJogT
33
37
  from rainbow.rb_flat_buffers.SLAMNAV.ResponseSetLed import ResponseSetLedT
34
38
  from rainbow.rb_flat_buffers.SLAMNAV.ResponseSetMotor import ResponseSetMotorT
@@ -313,7 +317,7 @@ class RBAmrControlSDK(RBBaseSDK):
313
317
  safety_flag = SafetyFlagT()
314
318
  safety_flag.name = flag.name
315
319
  safety_flag.value = flag.value
316
- req.safetyFlag.add(safety_flag)
320
+ req.safetyFlag.append(safety_flag)
317
321
 
318
322
  # 2) 요청 전송
319
323
  result = self.zenoh_client.query_one(
@@ -889,6 +893,92 @@ class RBAmrControlSDK(RBBaseSDK):
889
893
 
890
894
  return result["obj_payload"]
891
895
 
896
+ def control_set_avoid(
897
+ self,
898
+ robot_model: str,
899
+ switch: bool,
900
+ req_id: str | None = None,
901
+ flow_manager_args: FlowManagerArgs | None = None,
902
+ ) -> ResponseSetAvoidT:
903
+ """
904
+ [회피 모드 제어]
905
+ - req_id: 요청 ID
906
+ - switch: 회피 모드 켜기/끄기 (True: 켜기, False: 끄기)
907
+ - ResponseSetAvoidT 객체 반환
908
+ """
909
+
910
+ if req_id is None:
911
+ req_id = str(uuid.uuid4())
912
+
913
+ # 1) RequestSetAvoidT 객체 생성
914
+ req = RequestSetAvoidT()
915
+ req.id = req_id
916
+ req.switch = switch
917
+
918
+ # 2) 요청 전송
919
+ result = self.zenoh_client.query_one(
920
+ f"amr/{robot_model}/control/setAvoid",
921
+ flatbuffer_req_obj=req,
922
+ flatbuffer_res_T_class=ResponseSetAvoidT,
923
+ flatbuffer_buf_size=125,
924
+ timeout=3,
925
+ )
926
+
927
+ # 3) 결과 처리 및 반환
928
+ if result.get("obj_payload") is None:
929
+ raise RuntimeError("Call Control Motor failed: obj_payload is None")
930
+
931
+ if flow_manager_args is not None:
932
+ if result["dict_payload"].get("result") == "accept":
933
+ flow_manager_args.done()
934
+ else:
935
+ raise RuntimeError(result["dict_payload"].get("message"))
936
+
937
+ return result["obj_payload"]
938
+
939
+ def control_set_detect_mode(
940
+ self,
941
+ robot_model: str,
942
+ switch: bool,
943
+ req_id: str | None = None,
944
+ flow_manager_args: FlowManagerArgs | None = None,
945
+ ) -> ResponseSetDetectModeT:
946
+ """
947
+ [탐지 모드 제어]
948
+ - req_id: 요청 ID
949
+ - switch: 탐지 모드 켜기/끄기 (True: 켜기, False: 끄기)
950
+ - ResponseSetDetectModeT 객체 반환
951
+ """
952
+
953
+ if req_id is None:
954
+ req_id = str(uuid.uuid4())
955
+
956
+ # 1) RequestSetDetectModeT 객체 생성
957
+ req = RequestSetDetectModeT()
958
+ req.id = req_id
959
+ req.switch = switch
960
+
961
+ # 2) 요청 전송
962
+ result = self.zenoh_client.query_one(
963
+ f"amr/{robot_model}/control/setDetectMode",
964
+ flatbuffer_req_obj=req,
965
+ flatbuffer_res_T_class=ResponseSetDetectModeT,
966
+ flatbuffer_buf_size=125,
967
+ timeout=3,
968
+ )
969
+
970
+ # 3) 결과 처리 및 반환
971
+ if result.get("obj_payload") is None:
972
+ raise RuntimeError("Call Control Motor failed: obj_payload is None")
973
+
974
+ if flow_manager_args is not None:
975
+ if result["dict_payload"].get("result") == "accept":
976
+ flow_manager_args.done()
977
+ else:
978
+ raise RuntimeError(result["dict_payload"].get("message"))
979
+
980
+ return result["obj_payload"]
981
+
892
982
  # def control_sensor_mode(self, robot_model: str, req_id: str, command: str, control: bool, frequency: int) -> ResponseSensorModeT:
893
983
  # """
894
984
  # [센서 모드 제어]
@@ -982,14 +1072,14 @@ class RBAmrControlSDK(RBBaseSDK):
982
1072
 
983
1073
  # return result["obj_payload"]
984
1074
 
985
- def control_get_result_dock(self, robot_model: str) -> ResultControlDockT:
1075
+ async def control_get_result_dock(self, robot_model: str) -> ResultControlDockT:
986
1076
  """
987
1077
  [도킹 결과 대기 및 조회]
988
1078
  - robot_model: 로봇 모델명
989
1079
  - ResultControlDockT 객체 반환
990
1080
  """
991
1081
 
992
- result = self.zenoh_client.receive_one(
1082
+ result = await self.zenoh_client.receive_one(
993
1083
  f"amr/{robot_model}/control/resultDock", flatbuffer_obj_t=ResultControlDockT, timeout=10
994
1084
  )
995
1085
  return result.get("obj_payload")
@@ -15,7 +15,7 @@ from rainbow.rb_sdk.base import RBBaseSDK
15
15
  class RBAmrFileSDK(RBBaseSDK):
16
16
  """Rainbow Robotics AMR File SDK"""
17
17
 
18
- async def get_file_meta(self, robot_model: str, file_path: str, preferred_chunk_size: int) -> ResponseGetFileMetaT:
18
+ def get_file_meta(self, robot_model: str, file_path: str, preferred_chunk_size: int) -> ResponseGetFileMetaT:
19
19
  """
20
20
  [File Meta 조회]
21
21
  - robot_model: 요청을 보낼 로봇 모델
@@ -43,7 +43,7 @@ class RBAmrFileSDK(RBBaseSDK):
43
43
 
44
44
  return result["obj_payload"]
45
45
 
46
- async def get_file_chunk(self, robot_model: str, file_path: str, idx: int, chunk_size: int) -> ResponseGetFileChunkT:
46
+ def get_file_chunk(self, robot_model: str, file_path: str, idx: int, chunk_size: int) -> ResponseGetFileChunkT:
47
47
  """
48
48
  [Map File Chunk 조회]
49
49
  - robot_model: 요청을 보낼 로봇 모델
@@ -74,7 +74,7 @@ class RBAmrFileSDK(RBBaseSDK):
74
74
 
75
75
  return result["obj_payload"]
76
76
 
77
- async def compress_files(self, robot_model: str, base_dir: str, source_names: list[str], output_name: str) -> ResponseCompressFilesT:
77
+ def compress_files(self, robot_model: str, base_dir: str, source_names: list[str], output_name: str) -> ResponseCompressFilesT:
78
78
  """
79
79
  [Files Compress 압축]
80
80
  - robot_model: 요청을 보낼 로봇 모델
@@ -105,7 +105,7 @@ class RBAmrFileSDK(RBBaseSDK):
105
105
 
106
106
  return result["obj_payload"]
107
107
 
108
- async def decompress_file(self, robot_model: str, source_path: str, output_path: str) -> ResponseDecompressFileT:
108
+ def decompress_file(self, robot_model: str, source_path: str, output_path: str) -> ResponseDecompressFileT:
109
109
  """
110
110
  [File Decompress 압축 해제]
111
111
  - robot_model: 요청을 보낼 로봇 모델
@@ -134,7 +134,7 @@ class RBAmrFileSDK(RBBaseSDK):
134
134
 
135
135
  return result["obj_payload"]
136
136
 
137
- async def delete_file(self, robot_model: str, file_path: str) -> ResponseDeleteFileT:
137
+ def delete_file(self, robot_model: str, file_path: str) -> ResponseDeleteFileT:
138
138
  """
139
139
  [File Delete 파일 삭제]
140
140
  - robot_model: 요청을 보낼 로봇 모델
@@ -393,13 +393,13 @@ class RBAmrLocalizationSDK(RBBaseSDK):
393
393
  return result["obj_payload"]
394
394
 
395
395
 
396
- def get_localization_result(self, robot_model: str) -> ResultLocalizationT:
396
+ async def get_localization_result(self, robot_model: str) -> ResultLocalizationT:
397
397
  """
398
398
  [위치 추정 결과 조회]
399
399
  - robot_model: 로봇 모델명
400
400
  - ResultLocalizationT 객체 반환
401
401
  """
402
- result = self.zenoh_client.receive_one(
402
+ result = await self.zenoh_client.receive_one(
403
403
  f"amr/{robot_model}/localization/result",
404
404
  flatbuffer_obj_t=ResultLocalizationT,
405
405
  timeout=10