pm2cd 0.1.1__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.
- pm2cd-0.1.1/PKG-INFO +1454 -0
- pm2cd-0.1.1/README.md +1431 -0
- pm2cd-0.1.1/pyproject.toml +53 -0
- pm2cd-0.1.1/setup.cfg +4 -0
- pm2cd-0.1.1/src/pm2cd/__init__.py +3 -0
- pm2cd-0.1.1/src/pm2cd/core/__init__.py +12 -0
- pm2cd-0.1.1/src/pm2cd/core/communication_tcp.py +416 -0
- pm2cd-0.1.1/src/pm2cd/core/controller_status.py +35 -0
- pm2cd-0.1.1/src/pm2cd/core/data.py +32 -0
- pm2cd-0.1.1/src/pm2cd/core/errors.py +10 -0
- pm2cd-0.1.1/src/pm2cd/core/home_status.py +31 -0
- pm2cd-0.1.1/src/pm2cd/core/limit_status.py +71 -0
- pm2cd-0.1.1/src/pm2cd/core/limit_switch_setting.py +163 -0
- pm2cd-0.1.1/src/pm2cd/core/motor_setting.py +39 -0
- pm2cd-0.1.1/src/pm2cd/core/motor_status.py +120 -0
- pm2cd-0.1.1/src/pm2cd/core/stop_mode.py +27 -0
- pm2cd-0.1.1/src/pm2cd/core/version_info.py +129 -0
- pm2cd-0.1.1/src/pm2cd/pm2cd_ctrl.py +1355 -0
- pm2cd-0.1.1/src/pm2cd/pm2cd_device.py +2287 -0
- pm2cd-0.1.1/src/pm2cd/pm2cd_single.py +2105 -0
- pm2cd-0.1.1/src/pm2cd/server_fastapi/__init__.py +24 -0
- pm2cd-0.1.1/src/pm2cd/server_fastapi/__init__.pyi +15 -0
- pm2cd-0.1.1/src/pm2cd/server_fastapi/client_async.py +27 -0
- pm2cd-0.1.1/src/pm2cd/server_fastapi/client_async.pyi +108 -0
- pm2cd-0.1.1/src/pm2cd/server_fastapi/client_sync.py +27 -0
- pm2cd-0.1.1/src/pm2cd/server_fastapi/client_sync.pyi +107 -0
- pm2cd-0.1.1/src/pm2cd/server_fastapi/make_pyi.py +42 -0
- pm2cd-0.1.1/src/pm2cd/server_fastapi/server.py +62 -0
- pm2cd-0.1.1/src/pm2cd.egg-info/PKG-INFO +1454 -0
- pm2cd-0.1.1/src/pm2cd.egg-info/SOURCES.txt +31 -0
- pm2cd-0.1.1/src/pm2cd.egg-info/dependency_links.txt +1 -0
- pm2cd-0.1.1/src/pm2cd.egg-info/requires.txt +15 -0
- pm2cd-0.1.1/src/pm2cd.egg-info/top_level.txt +1 -0
pm2cd-0.1.1/PKG-INFO
ADDED
|
@@ -0,0 +1,1454 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: pm2cd
|
|
3
|
+
Version: 0.1.1
|
|
4
|
+
Summary: tuji pm2cd
|
|
5
|
+
Author-email: Kengo NAKADA <kengo.nakada@email.com>
|
|
6
|
+
Requires-Python: >=3.10
|
|
7
|
+
Description-Content-Type: text/markdown
|
|
8
|
+
Requires-Dist: xlogger-py
|
|
9
|
+
Requires-Dist: dataclasses
|
|
10
|
+
Requires-Dist: coloredlogs
|
|
11
|
+
Requires-Dist: colorlog
|
|
12
|
+
Requires-Dist: pytest
|
|
13
|
+
Requires-Dist: pytest-asyncio
|
|
14
|
+
Requires-Dist: pyyaml
|
|
15
|
+
Requires-Dist: toml
|
|
16
|
+
Requires-Dist: nest_asyncio
|
|
17
|
+
Requires-Dist: sphinx
|
|
18
|
+
Requires-Dist: myst-parser
|
|
19
|
+
Requires-Dist: sphinx-autobuild
|
|
20
|
+
Requires-Dist: sphinx-rtd-theme
|
|
21
|
+
Requires-Dist: sphinxcontrib-napoleon
|
|
22
|
+
Requires-Dist: linkify-it-py
|
|
23
|
+
|
|
24
|
+
# pm2cd
|
|
25
|
+
|
|
26
|
+
PM2CD / PM2C-06A を Python から制御するためのパッケージです。
|
|
27
|
+
|
|
28
|
+
本パッケージは、既存の C版/MADOCA Device handler
|
|
29
|
+
の実装思想と装置操作の意味を参照しながら、 Python
|
|
30
|
+
では通信、装置固有処理、データ解析、利用者向け制御、multi-process 実行、
|
|
31
|
+
FastAPI 通信を分離して構成しています。
|
|
32
|
+
|
|
33
|
+
現在のバージョンは **v0.1.0** です。
|
|
34
|
+
|
|
35
|
+
この README は、単なるインストールメモではなく、PM2CD Python 版の
|
|
36
|
+
総合マニュアル・設計仕様・チュートリアルとして記述しています。
|
|
37
|
+
|
|
38
|
+
------------------------------------------------------------------------
|
|
39
|
+
|
|
40
|
+
## 1. 対象
|
|
41
|
+
|
|
42
|
+
対象装置は PM2CD / PM2C-06A です。
|
|
43
|
+
|
|
44
|
+
PM16C-16 と PM2CD / PM2C-06A は同一装置ではありません。 PM16C-16
|
|
45
|
+
の仕様をそのまま PM2CD の装置仕様として流用しません。
|
|
46
|
+
|
|
47
|
+
一方、既存の C版 `dev_pm16c16_*` Device handler 群には、 PM2CD Python
|
|
48
|
+
版を設計する上で重要な先行実装があります。
|
|
49
|
+
|
|
50
|
+
Python 版では、それら C ファイルを機械的に一対一移植するのではなく、
|
|
51
|
+
|
|
52
|
+
- 一つの意味ある装置操作を一つの Device handler として扱う
|
|
53
|
+
- 一つの操作に複数コマンドが必要なら Device 層で完結させる
|
|
54
|
+
- 通信そのものは共通通信層へ分離する
|
|
55
|
+
- raw response の複合解析は core parser へ分離する
|
|
56
|
+
- Ctrl は raw bit / nibble / command string を利用者へ露出しない
|
|
57
|
+
|
|
58
|
+
という設計思想を引き継いでいます。
|
|
59
|
+
|
|
60
|
+
------------------------------------------------------------------------
|
|
61
|
+
|
|
62
|
+
## 2. C版/MADOCA と Python 版の関係
|
|
63
|
+
|
|
64
|
+
### 2.1 C版の位置づけ
|
|
65
|
+
|
|
66
|
+
既存 C版は MADOCA 環境の Device handler として実装されてきたコードです。
|
|
67
|
+
|
|
68
|
+
今回 Python 版の基準として参照しているのは、MADOCA 全体のネットワーク
|
|
69
|
+
API を Python へ移植することではなく、Device handler
|
|
70
|
+
内部で実際に行われている
|
|
71
|
+
|
|
72
|
+
- command 生成
|
|
73
|
+
- send / receive
|
|
74
|
+
- 複数 command の処理順序
|
|
75
|
+
- response の変換
|
|
76
|
+
- 装置操作としての handler の粒度
|
|
77
|
+
|
|
78
|
+
です。
|
|
79
|
+
|
|
80
|
+
確認してきた C版 handler には、rotate/check_rotate、number/rate 変換、
|
|
81
|
+
emergency stop、backlash、display、hold、limit、pause、pulse、rate、
|
|
82
|
+
speed、speed mode、status/status_all、SETLS、TTL、version、home、
|
|
83
|
+
ALLREP、remote、stop、CRLF 送受信などがあります。
|
|
84
|
+
|
|
85
|
+
### 2.2 Python 版は C版の一対一翻訳ではない
|
|
86
|
+
|
|
87
|
+
Python 版では C版の責務を次のように再配置しています。
|
|
88
|
+
|
|
89
|
+
``` text
|
|
90
|
+
C版/MADOCA
|
|
91
|
+
Device handler
|
|
92
|
+
|
|
|
93
|
+
| 装置操作の意味・処理順序を参照
|
|
94
|
+
v
|
|
95
|
+
Python
|
|
96
|
+
PM2CDDevice
|
|
97
|
+
+ core parser
|
|
98
|
+
+ Communication
|
|
99
|
+
+ PM2CDsingle
|
|
100
|
+
+ PM2CD
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
例えば C版の一つの handler が、
|
|
104
|
+
|
|
105
|
+
1. 設定値を問い合わせる
|
|
106
|
+
2. 必要な bit を変更する
|
|
107
|
+
3. 設定 command を送る
|
|
108
|
+
4. 本来の操作 command を送る
|
|
109
|
+
|
|
110
|
+
という処理を行う場合、Python 版でも「一つの意味ある装置操作」として
|
|
111
|
+
`PM2CDDevice` 内で完結させます。
|
|
112
|
+
|
|
113
|
+
`set_limit()` はその代表例です。
|
|
114
|
+
|
|
115
|
+
``` text
|
|
116
|
+
SETLS?x
|
|
117
|
+
|
|
|
118
|
+
v
|
|
119
|
+
LimitSwitchSetting
|
|
120
|
+
|
|
|
121
|
+
+-- software limit が無効なら enable
|
|
122
|
+
|
|
|
123
|
+
v
|
|
124
|
+
SETLSx...
|
|
125
|
+
|
|
|
126
|
+
v
|
|
127
|
+
FLx... / BLx...
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
利用者に `SETLS?` と `FL/BL` を別々に操作させる設計にはしません。
|
|
131
|
+
|
|
132
|
+
### 2.3 MADOCA と Python server は別レイヤー
|
|
133
|
+
|
|
134
|
+
C版で使用されてきた MADOCA と、Python 版で使用する FastAPI /
|
|
135
|
+
`ese774_frame` は同じ通信 framework ではありません。
|
|
136
|
+
|
|
137
|
+
Python 版 PM2CD は DeviceClass として単独でも利用でき、 必要な場合に
|
|
138
|
+
FastAPI server/client を上に載せます。
|
|
139
|
+
|
|
140
|
+
したがって Python 版の設計では、
|
|
141
|
+
|
|
142
|
+
``` text
|
|
143
|
+
装置制御ロジック
|
|
144
|
+
!=
|
|
145
|
+
ネットワーク framework
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
を明確に分離しています。
|
|
149
|
+
|
|
150
|
+
------------------------------------------------------------------------
|
|
151
|
+
|
|
152
|
+
## 3. Python 版の全体構成
|
|
153
|
+
|
|
154
|
+
v0.1.0 の基本構造は次の通りです。
|
|
155
|
+
|
|
156
|
+
``` text
|
|
157
|
+
利用プログラム
|
|
158
|
+
|
|
|
159
|
+
+-- local
|
|
160
|
+
| |
|
|
161
|
+
| +--> PM2CDsingle
|
|
162
|
+
| |
|
|
163
|
+
| `--> PM2CD
|
|
164
|
+
|
|
|
165
|
+
`-- network
|
|
166
|
+
|
|
|
167
|
+
+--> SyncPM2CDClient / AsyncPM2CDClient
|
|
168
|
+
|
|
|
169
|
+
v
|
|
170
|
+
FastAPI / ese774_frame
|
|
171
|
+
|
|
|
172
|
+
v
|
|
173
|
+
PM2CD
|
|
174
|
+
|
|
|
175
|
+
v
|
|
176
|
+
ProcessExecutor
|
|
177
|
+
|
|
|
178
|
+
+--> PM2CDsingle worker 1
|
|
179
|
+
+--> PM2CDsingle worker 2
|
|
180
|
+
+--> ...
|
|
181
|
+
|
|
|
182
|
+
v
|
|
183
|
+
PM2CDDevice
|
|
184
|
+
|
|
|
185
|
+
v
|
|
186
|
+
shared Communication proxy
|
|
187
|
+
|
|
|
188
|
+
v
|
|
189
|
+
Communication x 1
|
|
190
|
+
|
|
|
191
|
+
v
|
|
192
|
+
TCP + CRLF
|
|
193
|
+
|
|
|
194
|
+
v
|
|
195
|
+
PM2CD / PM2C-06A
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
受信データについては、
|
|
199
|
+
|
|
200
|
+
``` text
|
|
201
|
+
raw response
|
|
202
|
+
|
|
|
203
|
+
v
|
|
204
|
+
core parser
|
|
205
|
+
|
|
|
206
|
+
v
|
|
207
|
+
frozen dataclass / Python value
|
|
208
|
+
|
|
|
209
|
+
v
|
|
210
|
+
PM2CDDevice
|
|
211
|
+
|
|
|
212
|
+
v
|
|
213
|
+
PM2CDsingle
|
|
214
|
+
|
|
|
215
|
+
v
|
|
216
|
+
PM2CD / client
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
という流れになります。
|
|
220
|
+
|
|
221
|
+
------------------------------------------------------------------------
|
|
222
|
+
|
|
223
|
+
## 4. 各層の責務
|
|
224
|
+
|
|
225
|
+
### 4.1 `Communication`
|
|
226
|
+
|
|
227
|
+
TCP 接続と文字列送受信だけを担当します。
|
|
228
|
+
|
|
229
|
+
主な責務は、
|
|
230
|
+
|
|
231
|
+
- TCP connect / disconnect
|
|
232
|
+
- command への CRLF 付加
|
|
233
|
+
- send
|
|
234
|
+
- receive
|
|
235
|
+
- query
|
|
236
|
+
- timeout / socket error 処理
|
|
237
|
+
- receive buffer 管理
|
|
238
|
+
|
|
239
|
+
です。
|
|
240
|
+
|
|
241
|
+
PM2CD 固有の `STS?`、`SETLS?`、`FL?` などの意味は知りません。
|
|
242
|
+
|
|
243
|
+
`query()` は send と receive を同一 lock 範囲で処理し、
|
|
244
|
+
要求と応答の対応を維持します。
|
|
245
|
+
|
|
246
|
+
### 4.2 `core`
|
|
247
|
+
|
|
248
|
+
装置の複合 response を意味のある Python データへ変換します。
|
|
249
|
+
|
|
250
|
+
現在の主要データ型は frozen dataclass として扱います。
|
|
251
|
+
|
|
252
|
+
- `MotorStatus`
|
|
253
|
+
- `ControllerStatus`
|
|
254
|
+
- `HomeStatus`
|
|
255
|
+
- `LimitStatus`
|
|
256
|
+
- `MotorSetting`
|
|
257
|
+
- `LimitSwitchSetting`
|
|
258
|
+
- `StopMode`
|
|
259
|
+
|
|
260
|
+
データ保持と parsing は分離します。
|
|
261
|
+
|
|
262
|
+
``` text
|
|
263
|
+
raw response
|
|
264
|
+
|
|
|
265
|
+
v
|
|
266
|
+
parse_xxx()
|
|
267
|
+
|
|
|
268
|
+
v
|
|
269
|
+
@dataclass(frozen=True)
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
解析不能な response について、不正な状態 object を無理に生成せず、 取得
|
|
273
|
+
API の失敗として `None` を返す設計を基本とします。
|
|
274
|
+
|
|
275
|
+
### 4.3 `PM2CDDevice`
|
|
276
|
+
|
|
277
|
+
装置固有の実 handler 層です。
|
|
278
|
+
|
|
279
|
+
ここが C版 Device handler に最も近い責務を持ちます。
|
|
280
|
+
|
|
281
|
+
- command 名を知る
|
|
282
|
+
- command を組み立てる
|
|
283
|
+
- 入力値を検証する
|
|
284
|
+
- `Communication` を使用して send/query する
|
|
285
|
+
- 必要な複数 command を一つの操作として実行する
|
|
286
|
+
- core parser を呼ぶ
|
|
287
|
+
- 装置固有 response を Python 値へ変換する
|
|
288
|
+
|
|
289
|
+
Device を単純な `send()` / `query()` wrapper にはしません。
|
|
290
|
+
|
|
291
|
+
### 4.4 `PM2CDsingle`
|
|
292
|
+
|
|
293
|
+
単一 process で動作する高水準の制御クラスです。
|
|
294
|
+
|
|
295
|
+
主な責務は、
|
|
296
|
+
|
|
297
|
+
- 利用者向け API
|
|
298
|
+
- default `motor`
|
|
299
|
+
- 移動コンテキスト
|
|
300
|
+
- `wait_for_complete()`
|
|
301
|
+
- backlash を含む位置決め完了判定
|
|
302
|
+
- Device API を意味ベースの公開 API へ整理
|
|
303
|
+
|
|
304
|
+
です。
|
|
305
|
+
|
|
306
|
+
`PM2CDsingle` は `Communication` の外部 injection に対応しています。
|
|
307
|
+
|
|
308
|
+
``` python
|
|
309
|
+
ctrl = PM2CDsingle(
|
|
310
|
+
ip_address=IP_ADDRESS,
|
|
311
|
+
communication=communication,
|
|
312
|
+
)
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
この dependency injection point は test 用だけではなく、 v0.1.0 の
|
|
316
|
+
multi-process 構成で一つの物理 Communication を 複数 worker
|
|
317
|
+
から使用するためにも利用します。
|
|
318
|
+
|
|
319
|
+
### 4.5 `PM2CD`
|
|
320
|
+
|
|
321
|
+
v0.1.0 では、利用者向け `PM2CD` は `ProcessExecutor` を使用する
|
|
322
|
+
multi-process facade です。
|
|
323
|
+
|
|
324
|
+
公開 API の意味は `PM2CDsingle` と揃え、 実際の handler 実行を worker
|
|
325
|
+
process へ dispatch します。
|
|
326
|
+
|
|
327
|
+
``` text
|
|
328
|
+
PM2CD.method(...)
|
|
329
|
+
|
|
|
330
|
+
v
|
|
331
|
+
ProcessExecutor.submit(...)
|
|
332
|
+
|
|
|
333
|
+
v
|
|
334
|
+
PM2CDsingle.method(...)
|
|
335
|
+
|
|
|
336
|
+
v
|
|
337
|
+
ProcessExecutor.wait(...)
|
|
338
|
+
|
|
|
339
|
+
v
|
|
340
|
+
return value
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
このため利用者から見る API は同期的ですが、 内部では handler が worker
|
|
344
|
+
process で実行されます。
|
|
345
|
+
|
|
346
|
+
------------------------------------------------------------------------
|
|
347
|
+
|
|
348
|
+
## 5. `PM2CDsingle` と `PM2CD` の使い分け
|
|
349
|
+
|
|
350
|
+
### 5.1 `PM2CDsingle`
|
|
351
|
+
|
|
352
|
+
一つの Python process 内で直接装置を制御する場合に使用します。
|
|
353
|
+
|
|
354
|
+
``` python
|
|
355
|
+
from pm2cd.pm2cd_single import PM2CDsingle
|
|
356
|
+
|
|
357
|
+
ctrl = PM2CDsingle(
|
|
358
|
+
ip_address="10.170.10.62",
|
|
359
|
+
port=7777,
|
|
360
|
+
timeout_sec=3.0,
|
|
361
|
+
)
|
|
362
|
+
|
|
363
|
+
try:
|
|
364
|
+
ctrl.remote()
|
|
365
|
+
position = ctrl.get_position(0)
|
|
366
|
+
print(position)
|
|
367
|
+
finally:
|
|
368
|
+
ctrl.close()
|
|
369
|
+
```
|
|
370
|
+
|
|
371
|
+
構造は単純です。
|
|
372
|
+
|
|
373
|
+
``` text
|
|
374
|
+
application
|
|
375
|
+
|
|
|
376
|
+
v
|
|
377
|
+
PM2CDsingle
|
|
378
|
+
|
|
|
379
|
+
v
|
|
380
|
+
PM2CDDevice
|
|
381
|
+
|
|
|
382
|
+
v
|
|
383
|
+
Communication
|
|
384
|
+
|
|
|
385
|
+
v
|
|
386
|
+
PM2CD
|
|
387
|
+
```
|
|
388
|
+
|
|
389
|
+
### 5.2 `PM2CD`
|
|
390
|
+
|
|
391
|
+
worker process を使用する通常の multi-process 構成です。
|
|
392
|
+
|
|
393
|
+
``` python
|
|
394
|
+
from pm2cd.pm2cd_ctrl import PM2CD
|
|
395
|
+
|
|
396
|
+
ctrl = PM2CD(
|
|
397
|
+
ip_address="10.170.10.62",
|
|
398
|
+
port=7777,
|
|
399
|
+
timeout_sec=3.0,
|
|
400
|
+
worker_count=2,
|
|
401
|
+
)
|
|
402
|
+
|
|
403
|
+
try:
|
|
404
|
+
ctrl.remote()
|
|
405
|
+
position = ctrl.get_position(0)
|
|
406
|
+
print(position)
|
|
407
|
+
finally:
|
|
408
|
+
ctrl.close()
|
|
409
|
+
```
|
|
410
|
+
|
|
411
|
+
`worker_count` は `ProcessExecutor` の worker process 数です。
|
|
412
|
+
|
|
413
|
+
------------------------------------------------------------------------
|
|
414
|
+
|
|
415
|
+
## 6. なぜ複数 worker でも Communication は一つなのか
|
|
416
|
+
|
|
417
|
+
### 6.1 誤った構成
|
|
418
|
+
|
|
419
|
+
worker ごとに `PM2CDsingle` を通常生成すると、 各 worker が自分の
|
|
420
|
+
`Communication` を作ります。
|
|
421
|
+
|
|
422
|
+
``` text
|
|
423
|
+
worker 1 -> Communication 1 --+
|
|
424
|
+
worker 2 -> Communication 2 --+--> same PM2CD
|
|
425
|
+
worker 3 -> Communication 3 --+
|
|
426
|
+
```
|
|
427
|
+
|
|
428
|
+
各 `Communication` の lock は別 process / 別 instance なので、
|
|
429
|
+
装置全体の通信順序を保証しません。
|
|
430
|
+
|
|
431
|
+
### 6.2 v0.1.0 の構成
|
|
432
|
+
|
|
433
|
+
v0.1.0 では `BaseManager` が一つの `Communication` を所有し、 各 worker
|
|
434
|
+
には proxy を渡します。
|
|
435
|
+
|
|
436
|
+
``` text
|
|
437
|
+
worker 1 --+
|
|
438
|
+
worker 2 --+--> Communication proxy --> Communication x 1 --> PM2CD
|
|
439
|
+
worker N --+
|
|
440
|
+
```
|
|
441
|
+
|
|
442
|
+
したがって、
|
|
443
|
+
|
|
444
|
+
``` text
|
|
445
|
+
worker process N
|
|
446
|
+
PM2CDsingle N
|
|
447
|
+
Communication 1
|
|
448
|
+
TCP connection 1
|
|
449
|
+
```
|
|
450
|
+
|
|
451
|
+
となります。
|
|
452
|
+
|
|
453
|
+
これは `ProcessExecutor` が PM2CD
|
|
454
|
+
の通信を自動的に共有しているのではありません。
|
|
455
|
+
|
|
456
|
+
**物理 resource の ownership は PM2CD 側の設計です。**
|
|
457
|
+
|
|
458
|
+
------------------------------------------------------------------------
|
|
459
|
+
|
|
460
|
+
## 7. `ProcessExecutor` との関係
|
|
461
|
+
|
|
462
|
+
`ProcessExecutor` は PM2CD 専用 framework ではありません。
|
|
463
|
+
|
|
464
|
+
PM2CD 側が利用している主な機能は、
|
|
465
|
+
|
|
466
|
+
- worker process の生成
|
|
467
|
+
- `worker_factory(context)`
|
|
468
|
+
- handler dispatch
|
|
469
|
+
- `submit()`
|
|
470
|
+
- `wait()`
|
|
471
|
+
- `SharedContext`
|
|
472
|
+
- manager-backed shared state
|
|
473
|
+
- process-safe lock
|
|
474
|
+
|
|
475
|
+
です。
|
|
476
|
+
|
|
477
|
+
概念上の責務は次のように分離します。
|
|
478
|
+
|
|
479
|
+
``` text
|
|
480
|
+
ProcessExecutor
|
|
481
|
+
|
|
|
482
|
+
+-- process を管理する
|
|
483
|
+
+-- job を dispatch する
|
|
484
|
+
+-- shared context を提供する
|
|
485
|
+
|
|
|
486
|
+
`-- PM2CD protocol は知らない
|
|
487
|
+
|
|
488
|
+
PM2CD
|
|
489
|
+
|
|
|
490
|
+
+-- PM2CDsingle を worker として構成する
|
|
491
|
+
+-- Communication を一つだけ所有する
|
|
492
|
+
+-- controller state を SharedContext へ置く
|
|
493
|
+
|
|
|
494
|
+
`-- PM2CD 固有の resource ownership を決める
|
|
495
|
+
```
|
|
496
|
+
|
|
497
|
+
### 7.1 `worker_factory(context)`
|
|
498
|
+
|
|
499
|
+
PM2CD は `worker_factory(context)` を使用して各 worker の `PM2CDsingle`
|
|
500
|
+
を生成します。
|
|
501
|
+
|
|
502
|
+
その際、
|
|
503
|
+
|
|
504
|
+
- 共通 `Communication` proxy
|
|
505
|
+
- `SharedContext.state`
|
|
506
|
+
|
|
507
|
+
を worker に接続します。
|
|
508
|
+
|
|
509
|
+
### 7.2 shared state
|
|
510
|
+
|
|
511
|
+
worker が複数あると、通常の instance variable は worker ごとに別です。
|
|
512
|
+
|
|
513
|
+
PM2CD では少なくとも、
|
|
514
|
+
|
|
515
|
+
- default `motor`
|
|
516
|
+
- 移動コンテキスト
|
|
517
|
+
|
|
518
|
+
は worker をまたいで意味を維持する必要があります。
|
|
519
|
+
|
|
520
|
+
そのため `SharedContext.state` を使用します。
|
|
521
|
+
|
|
522
|
+
------------------------------------------------------------------------
|
|
523
|
+
|
|
524
|
+
## 8. 移動コンテキストと `wait_for_complete()`
|
|
525
|
+
|
|
526
|
+
`move()` / `move_relative()` は、単に command を送るだけではありません。
|
|
527
|
+
|
|
528
|
+
位置決め完了判定のため、モーターごとに直前の移動条件を保持します。
|
|
529
|
+
|
|
530
|
+
主な内容は、
|
|
531
|
+
|
|
532
|
+
- target position
|
|
533
|
+
- backlash 指定
|
|
534
|
+
- backlash enabled
|
|
535
|
+
- backlash value
|
|
536
|
+
|
|
537
|
+
です。
|
|
538
|
+
|
|
539
|
+
### 8.1 backlash なし
|
|
540
|
+
|
|
541
|
+
基本的な完了判定は、
|
|
542
|
+
|
|
543
|
+
``` text
|
|
544
|
+
move
|
|
545
|
+
|
|
|
546
|
+
v
|
|
547
|
+
active
|
|
548
|
+
|
|
|
549
|
+
v
|
|
550
|
+
target position + inactive
|
|
551
|
+
|
|
|
552
|
+
v
|
|
553
|
+
complete
|
|
554
|
+
```
|
|
555
|
+
|
|
556
|
+
です。
|
|
557
|
+
|
|
558
|
+
ただし短い移動では polling 間で active
|
|
559
|
+
状態を観測できない場合があるため、 active
|
|
560
|
+
を観測したこと自体を必須条件にはしません。
|
|
561
|
+
|
|
562
|
+
### 8.2 backlash あり
|
|
563
|
+
|
|
564
|
+
backlash 補正では概念的に、
|
|
565
|
+
|
|
566
|
+
``` text
|
|
567
|
+
target
|
|
568
|
+
|
|
|
569
|
+
v
|
|
570
|
+
backlash point
|
|
571
|
+
|
|
|
572
|
+
v
|
|
573
|
+
target
|
|
574
|
+
```
|
|
575
|
+
|
|
576
|
+
という追加動作が入ります。
|
|
577
|
+
|
|
578
|
+
そのため最初に target position で inactive になっただけでは、
|
|
579
|
+
補正完了と即断できません。
|
|
580
|
+
|
|
581
|
+
`wait_for_complete()` は直前の移動コンテキストを参照して、 最終 target
|
|
582
|
+
への復帰までを判定します。
|
|
583
|
+
|
|
584
|
+
短い backlash 動作では active/inactive 遷移が polling
|
|
585
|
+
間で縮退する場合も考慮します。
|
|
586
|
+
|
|
587
|
+
### 8.3 multi-process での共有
|
|
588
|
+
|
|
589
|
+
`move()` を worker 1、`wait_for_complete()` を worker 2
|
|
590
|
+
が処理する可能性があります。
|
|
591
|
+
|
|
592
|
+
そのため v0.1.0 の `PM2CD` では移動コンテキストを `SharedContext.state`
|
|
593
|
+
へ置きます。
|
|
594
|
+
|
|
595
|
+
``` text
|
|
596
|
+
worker 1: move()
|
|
597
|
+
|
|
|
598
|
+
v
|
|
599
|
+
SharedContext.state
|
|
600
|
+
|
|
|
601
|
+
v
|
|
602
|
+
worker 2: wait_for_complete()
|
|
603
|
+
```
|
|
604
|
+
|
|
605
|
+
これにより worker scheduling に依存せず同じ制御意味を維持します。
|
|
606
|
+
|
|
607
|
+
------------------------------------------------------------------------
|
|
608
|
+
|
|
609
|
+
## 9. `motor` property
|
|
610
|
+
|
|
611
|
+
`PM2CDsingle` / `PM2CD` は default motor を `motor` property
|
|
612
|
+
で保持します。
|
|
613
|
+
|
|
614
|
+
``` python
|
|
615
|
+
ctrl.motor = 0
|
|
616
|
+
position = ctrl.get_position()
|
|
617
|
+
```
|
|
618
|
+
|
|
619
|
+
各 API で motor を明示した場合は、その値を優先します。
|
|
620
|
+
|
|
621
|
+
``` python
|
|
622
|
+
position = ctrl.get_position(1)
|
|
623
|
+
```
|
|
624
|
+
|
|
625
|
+
multi-process `PM2CD` では default motor も shared state として扱い、
|
|
626
|
+
worker ごとに異なる default motor にならないようにします。
|
|
627
|
+
|
|
628
|
+
------------------------------------------------------------------------
|
|
629
|
+
|
|
630
|
+
## 10. FastAPI / `ese774_frame`
|
|
631
|
+
|
|
632
|
+
PM2CD は `ese774_frame` の完全自動ディスパッチを使用します。
|
|
633
|
+
|
|
634
|
+
基本設定は、
|
|
635
|
+
|
|
636
|
+
``` text
|
|
637
|
+
FastApiServer
|
|
638
|
+
api_spec=None
|
|
639
|
+
object_name="pm2cd"
|
|
640
|
+
```
|
|
641
|
+
|
|
642
|
+
です。
|
|
643
|
+
|
|
644
|
+
個別の Pydantic model や `ApiSpec` を PM2CD 側で列挙せず、
|
|
645
|
+
公開メソッドとアノテーションを利用して API を構成します。
|
|
646
|
+
|
|
647
|
+
### 10.1 dataclass の転送
|
|
648
|
+
|
|
649
|
+
PM2CD は状態取得 API で frozen dataclass を返します。
|
|
650
|
+
|
|
651
|
+
例:
|
|
652
|
+
|
|
653
|
+
- `MotorStatus`
|
|
654
|
+
- `ControllerStatus`
|
|
655
|
+
- `HomeStatus`
|
|
656
|
+
- `LimitStatus`
|
|
657
|
+
- `MotorSetting`
|
|
658
|
+
- `LimitSwitchSetting`
|
|
659
|
+
- `StopMode`
|
|
660
|
+
|
|
661
|
+
これらを完全自動ディスパッチで JSON 化し、 client
|
|
662
|
+
側で元の型へ復元するため、 **`ese774_frame v0.6.0` 以上を使用します。**
|
|
663
|
+
|
|
664
|
+
### 10.2 client
|
|
665
|
+
|
|
666
|
+
同期 client と非同期 client を使用できます。
|
|
667
|
+
|
|
668
|
+
``` text
|
|
669
|
+
SyncPM2CDClient
|
|
670
|
+
AsyncPM2CDClient
|
|
671
|
+
```
|
|
672
|
+
|
|
673
|
+
client は `object_name="pm2cd"` で server と対応します。
|
|
674
|
+
|
|
675
|
+
------------------------------------------------------------------------
|
|
676
|
+
|
|
677
|
+
## 11. server の起動
|
|
678
|
+
|
|
679
|
+
### 11.1 module 側
|
|
680
|
+
|
|
681
|
+
v0.1.0 の server module は worker 数を受け取れます。
|
|
682
|
+
|
|
683
|
+
``` python
|
|
684
|
+
from pm2cd.server import run
|
|
685
|
+
|
|
686
|
+
run(
|
|
687
|
+
worker_count=2,
|
|
688
|
+
)
|
|
689
|
+
```
|
|
690
|
+
|
|
691
|
+
内部では、
|
|
692
|
+
|
|
693
|
+
``` text
|
|
694
|
+
run(worker_count)
|
|
695
|
+
|
|
|
696
|
+
v
|
|
697
|
+
create_server(worker_count)
|
|
698
|
+
|
|
|
699
|
+
v
|
|
700
|
+
FastApiServer(device_kwargs)
|
|
701
|
+
|
|
|
702
|
+
v
|
|
703
|
+
PM2CD(worker_count=worker_count)
|
|
704
|
+
```
|
|
705
|
+
|
|
706
|
+
と渡されます。
|
|
707
|
+
|
|
708
|
+
server process の数と、PM2CD 内部の `ProcessExecutor.worker_count` は
|
|
709
|
+
別の概念です。
|
|
710
|
+
|
|
711
|
+
### 11.2 example server
|
|
712
|
+
|
|
713
|
+
実際の起動 example は worker 数をコード側で設定します。
|
|
714
|
+
|
|
715
|
+
``` python
|
|
716
|
+
from pm2cd.server import run
|
|
717
|
+
|
|
718
|
+
WORKER_COUNT = 2
|
|
719
|
+
|
|
720
|
+
|
|
721
|
+
def main() -> None:
|
|
722
|
+
run(
|
|
723
|
+
worker_count=WORKER_COUNT,
|
|
724
|
+
)
|
|
725
|
+
|
|
726
|
+
|
|
727
|
+
if __name__ == "__main__":
|
|
728
|
+
main()
|
|
729
|
+
```
|
|
730
|
+
|
|
731
|
+
worker 数のための CLI option は使用しません。
|
|
732
|
+
|
|
733
|
+
------------------------------------------------------------------------
|
|
734
|
+
|
|
735
|
+
## 12. 基本チュートリアル
|
|
736
|
+
|
|
737
|
+
以下では `PM2CD` を使用します。
|
|
738
|
+
|
|
739
|
+
### 12.1 接続と終了
|
|
740
|
+
|
|
741
|
+
``` python
|
|
742
|
+
from pm2cd.pm2cd_ctrl import PM2CD
|
|
743
|
+
|
|
744
|
+
ctrl = PM2CD(
|
|
745
|
+
ip_address="10.170.10.62",
|
|
746
|
+
port=7777,
|
|
747
|
+
timeout_sec=3.0,
|
|
748
|
+
worker_count=2,
|
|
749
|
+
)
|
|
750
|
+
|
|
751
|
+
try:
|
|
752
|
+
print(ctrl.is_connected())
|
|
753
|
+
finally:
|
|
754
|
+
ctrl.close()
|
|
755
|
+
```
|
|
756
|
+
|
|
757
|
+
### 12.2 REMOTE へ切り替える
|
|
758
|
+
|
|
759
|
+
``` python
|
|
760
|
+
ctrl.remote()
|
|
761
|
+
```
|
|
762
|
+
|
|
763
|
+
LOCAL へ戻す場合は、
|
|
764
|
+
|
|
765
|
+
``` python
|
|
766
|
+
ctrl.local()
|
|
767
|
+
```
|
|
768
|
+
|
|
769
|
+
です。
|
|
770
|
+
|
|
771
|
+
### 12.3 状態を取得する
|
|
772
|
+
|
|
773
|
+
``` python
|
|
774
|
+
status = ctrl.get_status(0)
|
|
775
|
+
|
|
776
|
+
if status is not None:
|
|
777
|
+
print(status.position)
|
|
778
|
+
print(status.is_busy)
|
|
779
|
+
```
|
|
780
|
+
|
|
781
|
+
全軸:
|
|
782
|
+
|
|
783
|
+
``` python
|
|
784
|
+
statuses = ctrl.get_status_all()
|
|
785
|
+
```
|
|
786
|
+
|
|
787
|
+
### 12.4 現在位置を取得する
|
|
788
|
+
|
|
789
|
+
``` python
|
|
790
|
+
position = ctrl.get_position(0)
|
|
791
|
+
print(position)
|
|
792
|
+
```
|
|
793
|
+
|
|
794
|
+
default motor を使用する場合:
|
|
795
|
+
|
|
796
|
+
``` python
|
|
797
|
+
ctrl.motor = 0
|
|
798
|
+
position = ctrl.get_position()
|
|
799
|
+
```
|
|
800
|
+
|
|
801
|
+
### 12.5 絶対位置移動
|
|
802
|
+
|
|
803
|
+
``` python
|
|
804
|
+
ctrl.move(
|
|
805
|
+
0,
|
|
806
|
+
1000,
|
|
807
|
+
backlash=False,
|
|
808
|
+
)
|
|
809
|
+
|
|
810
|
+
status = ctrl.wait_for_complete(
|
|
811
|
+
0,
|
|
812
|
+
timeout_sec=30.0,
|
|
813
|
+
)
|
|
814
|
+
```
|
|
815
|
+
|
|
816
|
+
### 12.6 backlash 付き位置決め
|
|
817
|
+
|
|
818
|
+
``` python
|
|
819
|
+
ctrl.move(
|
|
820
|
+
0,
|
|
821
|
+
1000,
|
|
822
|
+
backlash=True,
|
|
823
|
+
)
|
|
824
|
+
|
|
825
|
+
status = ctrl.wait_for_complete(
|
|
826
|
+
0,
|
|
827
|
+
timeout_sec=30.0,
|
|
828
|
+
)
|
|
829
|
+
```
|
|
830
|
+
|
|
831
|
+
`PM2CD` では移動コンテキストが worker 間で共有されるため、 `move()` と
|
|
832
|
+
`wait_for_complete()` が別 worker で実行されても backlash
|
|
833
|
+
条件を引き継ぎます。
|
|
834
|
+
|
|
835
|
+
### 12.7 相対移動
|
|
836
|
+
|
|
837
|
+
``` python
|
|
838
|
+
ctrl.move_relative(
|
|
839
|
+
0,
|
|
840
|
+
100,
|
|
841
|
+
backlash=True,
|
|
842
|
+
)
|
|
843
|
+
|
|
844
|
+
ctrl.wait_for_complete(
|
|
845
|
+
0,
|
|
846
|
+
timeout_sec=30.0,
|
|
847
|
+
)
|
|
848
|
+
```
|
|
849
|
+
|
|
850
|
+
### 12.8 通常停止と非常停止
|
|
851
|
+
|
|
852
|
+
通常停止:
|
|
853
|
+
|
|
854
|
+
``` python
|
|
855
|
+
ctrl.stop(0)
|
|
856
|
+
ctrl.stop_all()
|
|
857
|
+
```
|
|
858
|
+
|
|
859
|
+
非常停止:
|
|
860
|
+
|
|
861
|
+
``` python
|
|
862
|
+
ctrl.emergency_stop(0)
|
|
863
|
+
ctrl.emergency_stop_all()
|
|
864
|
+
```
|
|
865
|
+
|
|
866
|
+
通常停止と非常停止は別 API として扱います。
|
|
867
|
+
|
|
868
|
+
------------------------------------------------------------------------
|
|
869
|
+
|
|
870
|
+
## 13. 速度・rate・backlash
|
|
871
|
+
|
|
872
|
+
### 13.1 speed
|
|
873
|
+
|
|
874
|
+
``` python
|
|
875
|
+
speed = ctrl.get_speed(0)
|
|
876
|
+
ctrl.set_speed(0, 1000)
|
|
877
|
+
```
|
|
878
|
+
|
|
879
|
+
LOW / MIDDLE / HIGH をまとめて扱う API:
|
|
880
|
+
|
|
881
|
+
``` python
|
|
882
|
+
profile = ctrl.get_speed_profile(0)
|
|
883
|
+
```
|
|
884
|
+
|
|
885
|
+
個別 API:
|
|
886
|
+
|
|
887
|
+
``` text
|
|
888
|
+
get_high_speed / set_high_speed
|
|
889
|
+
get_middle_speed / set_middle_speed
|
|
890
|
+
get_low_speed / set_low_speed
|
|
891
|
+
```
|
|
892
|
+
|
|
893
|
+
### 13.2 rate
|
|
894
|
+
|
|
895
|
+
rate number:
|
|
896
|
+
|
|
897
|
+
``` python
|
|
898
|
+
number = ctrl.get_rate_number(0)
|
|
899
|
+
ctrl.set_rate_number(0, number)
|
|
900
|
+
```
|
|
901
|
+
|
|
902
|
+
rate 値:
|
|
903
|
+
|
|
904
|
+
``` python
|
|
905
|
+
rate = ctrl.get_rate(0)
|
|
906
|
+
ctrl.set_rate(0, rate)
|
|
907
|
+
```
|
|
908
|
+
|
|
909
|
+
変換 API:
|
|
910
|
+
|
|
911
|
+
``` python
|
|
912
|
+
rate = ctrl.number_to_rate(number)
|
|
913
|
+
number = ctrl.rate_to_number(rate)
|
|
914
|
+
```
|
|
915
|
+
|
|
916
|
+
### 13.3 backlash
|
|
917
|
+
|
|
918
|
+
``` python
|
|
919
|
+
backlash = ctrl.get_backlash(0)
|
|
920
|
+
ctrl.set_backlash(0, backlash)
|
|
921
|
+
```
|
|
922
|
+
|
|
923
|
+
------------------------------------------------------------------------
|
|
924
|
+
|
|
925
|
+
## 14. limit
|
|
926
|
+
|
|
927
|
+
PM2CD Python API では、無修飾の `limit` は software limit を意味します。
|
|
928
|
+
|
|
929
|
+
hardware limit は `hard_` を明示します。
|
|
930
|
+
|
|
931
|
+
### 14.1 software limit position
|
|
932
|
+
|
|
933
|
+
``` python
|
|
934
|
+
cw = ctrl.get_limit(0, "cw")
|
|
935
|
+
ccw = ctrl.get_limit(0, "ccw")
|
|
936
|
+
|
|
937
|
+
ctrl.set_limit(0, "cw", 10000)
|
|
938
|
+
ctrl.set_limit(0, "ccw", -10000)
|
|
939
|
+
```
|
|
940
|
+
|
|
941
|
+
### 14.2 software limit state
|
|
942
|
+
|
|
943
|
+
``` python
|
|
944
|
+
status = ctrl.get_limit_status(0)
|
|
945
|
+
```
|
|
946
|
+
|
|
947
|
+
意味順序:
|
|
948
|
+
|
|
949
|
+
``` text
|
|
950
|
+
[CW, CCW]
|
|
951
|
+
```
|
|
952
|
+
|
|
953
|
+
### 14.3 hardware limit state
|
|
954
|
+
|
|
955
|
+
``` python
|
|
956
|
+
status = ctrl.get_hard_limit_status(0)
|
|
957
|
+
```
|
|
958
|
+
|
|
959
|
+
意味順序:
|
|
960
|
+
|
|
961
|
+
``` text
|
|
962
|
+
[CW, CCW, HP]
|
|
963
|
+
```
|
|
964
|
+
|
|
965
|
+
### 14.4 enable
|
|
966
|
+
|
|
967
|
+
software/digital limit:
|
|
968
|
+
|
|
969
|
+
``` python
|
|
970
|
+
enabled = ctrl.get_limit_enabled(0)
|
|
971
|
+
ctrl.set_limit_enabled(0, True)
|
|
972
|
+
```
|
|
973
|
+
|
|
974
|
+
hardware limit:
|
|
975
|
+
|
|
976
|
+
``` python
|
|
977
|
+
enabled = ctrl.get_hard_limit_enabled(0)
|
|
978
|
+
ctrl.set_hard_limit_enabled(0, True)
|
|
979
|
+
```
|
|
980
|
+
|
|
981
|
+
### 14.5 normally closed / open
|
|
982
|
+
|
|
983
|
+
``` python
|
|
984
|
+
setting = ctrl.get_hard_limit_normally_closed(0)
|
|
985
|
+
|
|
986
|
+
ctrl.set_hard_limit_normally_closed(
|
|
987
|
+
0,
|
|
988
|
+
"cw",
|
|
989
|
+
True,
|
|
990
|
+
)
|
|
991
|
+
```
|
|
992
|
+
|
|
993
|
+
公開 API では raw `DYYY0yyy` を直接扱いません。
|
|
994
|
+
|
|
995
|
+
------------------------------------------------------------------------
|
|
996
|
+
|
|
997
|
+
## 15. HOME / HOLD / PAUSE
|
|
998
|
+
|
|
999
|
+
HOME:
|
|
1000
|
+
|
|
1001
|
+
``` text
|
|
1002
|
+
home
|
|
1003
|
+
find_home
|
|
1004
|
+
scan_home
|
|
1005
|
+
get_home_status
|
|
1006
|
+
set_home_status
|
|
1007
|
+
get_home_position
|
|
1008
|
+
set_home_position
|
|
1009
|
+
get_home_offset
|
|
1010
|
+
set_home_offset
|
|
1011
|
+
```
|
|
1012
|
+
|
|
1013
|
+
preset / JOG:
|
|
1014
|
+
|
|
1015
|
+
``` text
|
|
1016
|
+
get_preset_position
|
|
1017
|
+
set_preset_position
|
|
1018
|
+
get_jog_pulse
|
|
1019
|
+
set_jog_pulse
|
|
1020
|
+
```
|
|
1021
|
+
|
|
1022
|
+
HOLD:
|
|
1023
|
+
|
|
1024
|
+
``` text
|
|
1025
|
+
get_hold
|
|
1026
|
+
set_hold
|
|
1027
|
+
get_hold_on_time
|
|
1028
|
+
set_hold_on_time
|
|
1029
|
+
get_hold_off_time
|
|
1030
|
+
set_hold_off_time
|
|
1031
|
+
```
|
|
1032
|
+
|
|
1033
|
+
PAUSE:
|
|
1034
|
+
|
|
1035
|
+
``` text
|
|
1036
|
+
pause
|
|
1037
|
+
resume
|
|
1038
|
+
get_pause_status
|
|
1039
|
+
```
|
|
1040
|
+
|
|
1041
|
+
------------------------------------------------------------------------
|
|
1042
|
+
|
|
1043
|
+
## 16. motor / stop setting
|
|
1044
|
+
|
|
1045
|
+
motor setting:
|
|
1046
|
+
|
|
1047
|
+
``` text
|
|
1048
|
+
get_motor_setting
|
|
1049
|
+
set_motor_setting
|
|
1050
|
+
```
|
|
1051
|
+
|
|
1052
|
+
stop mode:
|
|
1053
|
+
|
|
1054
|
+
``` text
|
|
1055
|
+
get_stop_mode
|
|
1056
|
+
set_stop_mode
|
|
1057
|
+
```
|
|
1058
|
+
|
|
1059
|
+
取得値は dataclass として扱います。
|
|
1060
|
+
|
|
1061
|
+
------------------------------------------------------------------------
|
|
1062
|
+
|
|
1063
|
+
## 17. 主な公開 API
|
|
1064
|
+
|
|
1065
|
+
### 接続・mode
|
|
1066
|
+
|
|
1067
|
+
``` text
|
|
1068
|
+
motor
|
|
1069
|
+
is_connected
|
|
1070
|
+
connect
|
|
1071
|
+
disconnect
|
|
1072
|
+
remote
|
|
1073
|
+
local
|
|
1074
|
+
close
|
|
1075
|
+
```
|
|
1076
|
+
|
|
1077
|
+
### version / controller
|
|
1078
|
+
|
|
1079
|
+
``` text
|
|
1080
|
+
version
|
|
1081
|
+
get_version
|
|
1082
|
+
get_hardware_version
|
|
1083
|
+
get_controller_status
|
|
1084
|
+
controller_status
|
|
1085
|
+
```
|
|
1086
|
+
|
|
1087
|
+
### motion
|
|
1088
|
+
|
|
1089
|
+
``` text
|
|
1090
|
+
move
|
|
1091
|
+
move_relative
|
|
1092
|
+
scan
|
|
1093
|
+
constant_speed_scan
|
|
1094
|
+
jog
|
|
1095
|
+
scan_home
|
|
1096
|
+
home
|
|
1097
|
+
find_home
|
|
1098
|
+
stop
|
|
1099
|
+
stop_all
|
|
1100
|
+
emergency_stop
|
|
1101
|
+
emergency_stop_all
|
|
1102
|
+
get_rotate
|
|
1103
|
+
is_busy
|
|
1104
|
+
wait_for_complete
|
|
1105
|
+
```
|
|
1106
|
+
|
|
1107
|
+
### status / position
|
|
1108
|
+
|
|
1109
|
+
``` text
|
|
1110
|
+
get_status
|
|
1111
|
+
get_status_all
|
|
1112
|
+
status_all
|
|
1113
|
+
get_position
|
|
1114
|
+
set_position
|
|
1115
|
+
zero_position
|
|
1116
|
+
```
|
|
1117
|
+
|
|
1118
|
+
### speed / rate / backlash
|
|
1119
|
+
|
|
1120
|
+
``` text
|
|
1121
|
+
get_speed
|
|
1122
|
+
set_speed
|
|
1123
|
+
get_speed_profile
|
|
1124
|
+
set_speed_profile
|
|
1125
|
+
get_high_speed
|
|
1126
|
+
set_high_speed
|
|
1127
|
+
get_middle_speed
|
|
1128
|
+
set_middle_speed
|
|
1129
|
+
get_low_speed
|
|
1130
|
+
set_low_speed
|
|
1131
|
+
get_speed_mode
|
|
1132
|
+
set_speed_mode
|
|
1133
|
+
get_rate_number
|
|
1134
|
+
set_rate_number
|
|
1135
|
+
get_rate
|
|
1136
|
+
set_rate
|
|
1137
|
+
number_to_rate
|
|
1138
|
+
rate_to_number
|
|
1139
|
+
get_backlash
|
|
1140
|
+
set_backlash
|
|
1141
|
+
```
|
|
1142
|
+
|
|
1143
|
+
### limit
|
|
1144
|
+
|
|
1145
|
+
``` text
|
|
1146
|
+
get_limit
|
|
1147
|
+
set_limit
|
|
1148
|
+
get_limit_status
|
|
1149
|
+
get_limit_status_all
|
|
1150
|
+
get_hard_limit_status
|
|
1151
|
+
get_hard_limit_status_all
|
|
1152
|
+
get_limit_enabled
|
|
1153
|
+
set_limit_enabled
|
|
1154
|
+
get_hard_limit_enabled
|
|
1155
|
+
set_hard_limit_enabled
|
|
1156
|
+
get_hard_limit_normally_closed
|
|
1157
|
+
set_hard_limit_normally_closed
|
|
1158
|
+
get_limit_switch_setting
|
|
1159
|
+
```
|
|
1160
|
+
|
|
1161
|
+
### pause / hold
|
|
1162
|
+
|
|
1163
|
+
``` text
|
|
1164
|
+
pause
|
|
1165
|
+
resume
|
|
1166
|
+
get_pause_status
|
|
1167
|
+
get_hold
|
|
1168
|
+
set_hold
|
|
1169
|
+
get_hold_on_time
|
|
1170
|
+
set_hold_on_time
|
|
1171
|
+
get_hold_off_time
|
|
1172
|
+
set_hold_off_time
|
|
1173
|
+
```
|
|
1174
|
+
|
|
1175
|
+
### HOME / preset / JOG
|
|
1176
|
+
|
|
1177
|
+
``` text
|
|
1178
|
+
get_home_status
|
|
1179
|
+
set_home_status
|
|
1180
|
+
get_home_position
|
|
1181
|
+
set_home_position
|
|
1182
|
+
get_home_offset
|
|
1183
|
+
set_home_offset
|
|
1184
|
+
get_preset_position
|
|
1185
|
+
set_preset_position
|
|
1186
|
+
get_jog_pulse
|
|
1187
|
+
set_jog_pulse
|
|
1188
|
+
```
|
|
1189
|
+
|
|
1190
|
+
### setting
|
|
1191
|
+
|
|
1192
|
+
``` text
|
|
1193
|
+
get_motor_setting
|
|
1194
|
+
set_motor_setting
|
|
1195
|
+
get_stop_mode
|
|
1196
|
+
set_stop_mode
|
|
1197
|
+
```
|
|
1198
|
+
|
|
1199
|
+
------------------------------------------------------------------------
|
|
1200
|
+
|
|
1201
|
+
## 18. 戻り値の基本方針
|
|
1202
|
+
|
|
1203
|
+
装置制御 API は概ね次の方針です。
|
|
1204
|
+
|
|
1205
|
+
``` text
|
|
1206
|
+
操作成功/失敗 bool
|
|
1207
|
+
値取得成功 値
|
|
1208
|
+
値取得失敗 None
|
|
1209
|
+
```
|
|
1210
|
+
|
|
1211
|
+
取得 API は `Optional[...]` のアノテーションを持つものがあります。
|
|
1212
|
+
|
|
1213
|
+
状態・設定 object は frozen dataclass として扱い、
|
|
1214
|
+
取得後に状態を書き換える設計にはしません。
|
|
1215
|
+
|
|
1216
|
+
------------------------------------------------------------------------
|
|
1217
|
+
|
|
1218
|
+
## 19. エラーと入力検証
|
|
1219
|
+
|
|
1220
|
+
入力値は可能な限り `PM2CDDevice` 側で検証し、
|
|
1221
|
+
不正な値を装置へ送らない構成にします。
|
|
1222
|
+
|
|
1223
|
+
通信層の error は通信責務として扱い、 装置 response の解析失敗は parser
|
|
1224
|
+
/ Device の責務として扱います。
|
|
1225
|
+
|
|
1226
|
+
Ctrl は装置 protocol の raw error 表現を利用者 API
|
|
1227
|
+
の中心には置きません。
|
|
1228
|
+
|
|
1229
|
+
------------------------------------------------------------------------
|
|
1230
|
+
|
|
1231
|
+
## 20. server/client 利用時の構成
|
|
1232
|
+
|
|
1233
|
+
network 越しの利用では次の構成になります。
|
|
1234
|
+
|
|
1235
|
+
``` text
|
|
1236
|
+
client application
|
|
1237
|
+
|
|
|
1238
|
+
v
|
|
1239
|
+
SyncPM2CDClient
|
|
1240
|
+
or AsyncPM2CDClient
|
|
1241
|
+
|
|
|
1242
|
+
v
|
|
1243
|
+
HTTP / FastAPI
|
|
1244
|
+
|
|
|
1245
|
+
v
|
|
1246
|
+
ese774_frame FastApiServer
|
|
1247
|
+
|
|
|
1248
|
+
v
|
|
1249
|
+
PM2CD
|
|
1250
|
+
|
|
|
1251
|
+
v
|
|
1252
|
+
ProcessExecutor
|
|
1253
|
+
|
|
|
1254
|
+
v
|
|
1255
|
+
PM2CDsingle worker x N
|
|
1256
|
+
|
|
|
1257
|
+
v
|
|
1258
|
+
shared Communication
|
|
1259
|
+
|
|
|
1260
|
+
v
|
|
1261
|
+
PM2CD
|
|
1262
|
+
```
|
|
1263
|
+
|
|
1264
|
+
`PM2CD` の内部 worker 数を増やしても、 装置への TCP connection
|
|
1265
|
+
を増やさないことが v0.1.0 の重要な設計条件です。
|
|
1266
|
+
|
|
1267
|
+
------------------------------------------------------------------------
|
|
1268
|
+
|
|
1269
|
+
## 21. example の考え方
|
|
1270
|
+
|
|
1271
|
+
example は段階的に確認できるようにします。
|
|
1272
|
+
|
|
1273
|
+
### 21.1 single local
|
|
1274
|
+
|
|
1275
|
+
目的:
|
|
1276
|
+
|
|
1277
|
+
- framework を介さず PM2CDsingle 自体を確認する
|
|
1278
|
+
- 装置 protocol / Device / Ctrl の基準動作を確認する
|
|
1279
|
+
|
|
1280
|
+
### 21.2 multi local
|
|
1281
|
+
|
|
1282
|
+
目的:
|
|
1283
|
+
|
|
1284
|
+
- `PM2CD` + `ProcessExecutor` を確認する
|
|
1285
|
+
- worker process からの実制御を確認する
|
|
1286
|
+
- worker 数を2以上にしても Communication が一つである構成を確認する
|
|
1287
|
+
|
|
1288
|
+
### 21.3 FastAPI server/client
|
|
1289
|
+
|
|
1290
|
+
目的:
|
|
1291
|
+
|
|
1292
|
+
- `ese774_frame` の完全自動ディスパッチを確認する
|
|
1293
|
+
- dataclass の server/client 間転送を確認する
|
|
1294
|
+
- network 越しでも同じ PM2CD 公開 API を使用する
|
|
1295
|
+
|
|
1296
|
+
### 21.4 server 起動 example
|
|
1297
|
+
|
|
1298
|
+
worker 数は example script の定数で指定します。
|
|
1299
|
+
|
|
1300
|
+
``` python
|
|
1301
|
+
WORKER_COUNT = 2
|
|
1302
|
+
```
|
|
1303
|
+
|
|
1304
|
+
CLI option で worker 数を与える方式にはしません。
|
|
1305
|
+
|
|
1306
|
+
------------------------------------------------------------------------
|
|
1307
|
+
|
|
1308
|
+
## 22. 推奨する確認順序
|
|
1309
|
+
|
|
1310
|
+
装置を使った動作確認は、層を一度に増やさず次の順序で行います。
|
|
1311
|
+
|
|
1312
|
+
``` text
|
|
1313
|
+
1. Communication
|
|
1314
|
+
|
|
|
1315
|
+
2. PM2CDDevice
|
|
1316
|
+
|
|
|
1317
|
+
3. PM2CDsingle local
|
|
1318
|
+
|
|
|
1319
|
+
4. PM2CD multi local
|
|
1320
|
+
|
|
|
1321
|
+
5. FastAPI server
|
|
1322
|
+
|
|
|
1323
|
+
6. Sync/Async client
|
|
1324
|
+
```
|
|
1325
|
+
|
|
1326
|
+
multi-process の問題と network framework
|
|
1327
|
+
の問題を同時に切り分けないためです。
|
|
1328
|
+
|
|
1329
|
+
特に新しい motion API の確認では、一つの method を小さく確認してから
|
|
1330
|
+
次の層へ進めます。
|
|
1331
|
+
|
|
1332
|
+
------------------------------------------------------------------------
|
|
1333
|
+
|
|
1334
|
+
## 23. `close()` と resource ownership
|
|
1335
|
+
|
|
1336
|
+
multi-process `PM2CD` では `Communication` は全 worker の共有 resource
|
|
1337
|
+
です。
|
|
1338
|
+
|
|
1339
|
+
したがって、一つの worker に `PM2CDsingle.close()`
|
|
1340
|
+
を実行させてはいけません。
|
|
1341
|
+
|
|
1342
|
+
`PM2CD.close()` は、
|
|
1343
|
+
|
|
1344
|
+
``` text
|
|
1345
|
+
ProcessExecutor.close()
|
|
1346
|
+
|
|
|
1347
|
+
v
|
|
1348
|
+
shared Communication.close()
|
|
1349
|
+
|
|
|
1350
|
+
v
|
|
1351
|
+
CommunicationManager.shutdown()
|
|
1352
|
+
```
|
|
1353
|
+
|
|
1354
|
+
の順で終了します。
|
|
1355
|
+
|
|
1356
|
+
物理 resource を作成した owner が最後に一度だけ閉じる、という構成です。
|
|
1357
|
+
|
|
1358
|
+
------------------------------------------------------------------------
|
|
1359
|
+
|
|
1360
|
+
## 24. 設計上の重要事項
|
|
1361
|
+
|
|
1362
|
+
### 24.1 Ctrl と Device を混ぜない
|
|
1363
|
+
|
|
1364
|
+
Ctrl に command string を直接書き始めると、 C版で整理されていた Device
|
|
1365
|
+
handler の責務が崩れます。
|
|
1366
|
+
|
|
1367
|
+
装置固有 command は Device に置きます。
|
|
1368
|
+
|
|
1369
|
+
### 24.2 Device を薄くしすぎない
|
|
1370
|
+
|
|
1371
|
+
一つの意味ある操作に複数 command が必要なら、 その一連の処理は Device
|
|
1372
|
+
handler に残します。
|
|
1373
|
+
|
|
1374
|
+
### 24.3 core dataclass に処理を持たせすぎない
|
|
1375
|
+
|
|
1376
|
+
dataclass はデータを表します。
|
|
1377
|
+
|
|
1378
|
+
response parsing は parser 関数へ分離します。
|
|
1379
|
+
|
|
1380
|
+
### 24.4 ProcessExecutor に装置固有責務を入れない
|
|
1381
|
+
|
|
1382
|
+
ProcessExecutor は PM2CD の TCP socket や protocol を知りません。
|
|
1383
|
+
|
|
1384
|
+
Communication の共有方法は PM2CD が決めます。
|
|
1385
|
+
|
|
1386
|
+
### 24.5 shared は公開 API の概念にしない
|
|
1387
|
+
|
|
1388
|
+
worker 間で state を共有していても、 `get_shared_xxx()` のような専用 API
|
|
1389
|
+
を利用者へ追加しません。
|
|
1390
|
+
|
|
1391
|
+
shared state は multi-process 実装の内部事情です。
|
|
1392
|
+
|
|
1393
|
+
------------------------------------------------------------------------
|
|
1394
|
+
|
|
1395
|
+
## 25. dependency
|
|
1396
|
+
|
|
1397
|
+
FastAPI 完全自動ディスパッチを使用する場合:
|
|
1398
|
+
|
|
1399
|
+
``` text
|
|
1400
|
+
ese774_frame >= 0.6.0
|
|
1401
|
+
```
|
|
1402
|
+
|
|
1403
|
+
が必要です。
|
|
1404
|
+
|
|
1405
|
+
multi-process `PM2CD` は `ProcessExecutor` の、
|
|
1406
|
+
|
|
1407
|
+
``` text
|
|
1408
|
+
worker_factory
|
|
1409
|
+
SharedContext
|
|
1410
|
+
shared_context
|
|
1411
|
+
submit
|
|
1412
|
+
wait
|
|
1413
|
+
```
|
|
1414
|
+
|
|
1415
|
+
を使用します。
|
|
1416
|
+
|
|
1417
|
+
PM2CD と ProcessExecutor の責務は分離されており、 ProcessExecutor
|
|
1418
|
+
自体には PM2CD 固有コードを入れません。
|
|
1419
|
+
|
|
1420
|
+
------------------------------------------------------------------------
|
|
1421
|
+
|
|
1422
|
+
## 26. v0.1.0 の位置づけ
|
|
1423
|
+
|
|
1424
|
+
v0.0.x では主に、
|
|
1425
|
+
|
|
1426
|
+
- C版 Device handler の意味の整理
|
|
1427
|
+
- Communication / core / Device / Ctrl の責務分離
|
|
1428
|
+
- `PM2CDsingle` API の拡張
|
|
1429
|
+
- backlash を含む `wait_for_complete()`
|
|
1430
|
+
- frozen dataclass + parser
|
|
1431
|
+
- FastAPI 完全自動ディスパッチ
|
|
1432
|
+
|
|
1433
|
+
を整備しました。
|
|
1434
|
+
|
|
1435
|
+
v0.1.0 では、その single-process 制御ロジックを壊さず、 `PM2CD`
|
|
1436
|
+
を実用的な multi-process facade として成立させました。
|
|
1437
|
+
|
|
1438
|
+
中心となる設計は、
|
|
1439
|
+
|
|
1440
|
+
``` text
|
|
1441
|
+
PM2CDsingle worker x N
|
|
1442
|
+
+
|
|
1443
|
+
SharedContext
|
|
1444
|
+
+
|
|
1445
|
+
Communication x 1
|
|
1446
|
+
+
|
|
1447
|
+
TCP connection x 1
|
|
1448
|
+
```
|
|
1449
|
+
|
|
1450
|
+
です。
|
|
1451
|
+
|
|
1452
|
+
これにより、単一 process の装置制御クラス、multi-process 制御、 FastAPI
|
|
1453
|
+
server/client を同じ Device/Ctrl
|
|
1454
|
+
設計の上に積み上げる構成になっています。
|