pytmrobot 0.1.0__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.
- pytmrobot-0.1.0/LICENSE +21 -0
- pytmrobot-0.1.0/PKG-INFO +229 -0
- pytmrobot-0.1.0/README.md +176 -0
- pytmrobot-0.1.0/pyproject.toml +96 -0
- pytmrobot-0.1.0/pytmrobot/__init__.py +89 -0
- pytmrobot-0.1.0/pytmrobot/_client.py +161 -0
- pytmrobot-0.1.0/pytmrobot/_ft_base.py +115 -0
- pytmrobot-0.1.0/pytmrobot/_protocol.py +171 -0
- pytmrobot-0.1.0/pytmrobot/compliance.py +92 -0
- pytmrobot-0.1.0/pytmrobot/decision.py +122 -0
- pytmrobot-0.1.0/pytmrobot/exceptions.py +35 -0
- pytmrobot-0.1.0/pytmrobot/force.py +151 -0
- pytmrobot-0.1.0/pytmrobot/io.py +180 -0
- pytmrobot-0.1.0/pytmrobot/modbus.py +274 -0
- pytmrobot-0.1.0/pytmrobot/motion.py +297 -0
- pytmrobot-0.1.0/pytmrobot/py.typed +0 -0
- pytmrobot-0.1.0/pytmrobot/robot.py +287 -0
- pytmrobot-0.1.0/pytmrobot/script_builder.py +790 -0
- pytmrobot-0.1.0/pytmrobot/state.py +126 -0
- pytmrobot-0.1.0/pytmrobot/tag_manager.py +40 -0
- pytmrobot-0.1.0/pytmrobot/touchstop.py +119 -0
- pytmrobot-0.1.0/pytmrobot/types.py +123 -0
- pytmrobot-0.1.0/pytmrobot/vision.py +144 -0
- pytmrobot-0.1.0/pytmrobot.egg-info/PKG-INFO +229 -0
- pytmrobot-0.1.0/pytmrobot.egg-info/SOURCES.txt +36 -0
- pytmrobot-0.1.0/pytmrobot.egg-info/dependency_links.txt +1 -0
- pytmrobot-0.1.0/pytmrobot.egg-info/requires.txt +4 -0
- pytmrobot-0.1.0/pytmrobot.egg-info/top_level.txt +1 -0
- pytmrobot-0.1.0/setup.cfg +4 -0
- pytmrobot-0.1.0/tests/test_controllers.py +287 -0
- pytmrobot-0.1.0/tests/test_ft_controllers.py +292 -0
- pytmrobot-0.1.0/tests/test_io.py +181 -0
- pytmrobot-0.1.0/tests/test_motion.py +223 -0
- pytmrobot-0.1.0/tests/test_robot.py +239 -0
- pytmrobot-0.1.0/tests/test_script_builder.py +534 -0
- pytmrobot-0.1.0/tests/test_state.py +116 -0
- pytmrobot-0.1.0/tests/test_tag_manager.py +53 -0
- pytmrobot-0.1.0/tests/test_types.py +60 -0
pytmrobot-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Harry
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
pytmrobot-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: pytmrobot
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Python API for controlling Techman (TM) robots via Listen Node — no TMScript required
|
|
5
|
+
Author: Harry
|
|
6
|
+
License: MIT License
|
|
7
|
+
|
|
8
|
+
Copyright (c) 2026 Harry
|
|
9
|
+
|
|
10
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
11
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
12
|
+
in the Software without restriction, including without limitation the rights
|
|
13
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
14
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
15
|
+
furnished to do so, subject to the following conditions:
|
|
16
|
+
|
|
17
|
+
The above copyright notice and this permission notice shall be included in all
|
|
18
|
+
copies or substantial portions of the Software.
|
|
19
|
+
|
|
20
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
21
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
22
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
23
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
24
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
25
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
26
|
+
SOFTWARE.
|
|
27
|
+
|
|
28
|
+
Project-URL: Homepage, https://github.com/harry123180/TMDemo
|
|
29
|
+
Project-URL: Documentation, https://github.com/harry123180/TMDemo/blob/master/docs/wiki.md
|
|
30
|
+
Project-URL: Repository, https://github.com/harry123180/TMDemo
|
|
31
|
+
Project-URL: Bug Tracker, https://github.com/harry123180/TMDemo/issues
|
|
32
|
+
Project-URL: Changelog, https://github.com/harry123180/TMDemo/blob/master/CHANGELOG.md
|
|
33
|
+
Keywords: robot,techman,TM robot,collaborative robot,cobot,industrial automation,TMScript,Listen Node
|
|
34
|
+
Classifier: Development Status :: 3 - Alpha
|
|
35
|
+
Classifier: Intended Audience :: Developers
|
|
36
|
+
Classifier: Intended Audience :: Manufacturing
|
|
37
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
38
|
+
Classifier: Operating System :: OS Independent
|
|
39
|
+
Classifier: Programming Language :: Python :: 3
|
|
40
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
41
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
42
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
43
|
+
Classifier: Topic :: Scientific/Engineering
|
|
44
|
+
Classifier: Topic :: System :: Hardware
|
|
45
|
+
Classifier: Typing :: Typed
|
|
46
|
+
Requires-Python: >=3.10
|
|
47
|
+
Description-Content-Type: text/markdown
|
|
48
|
+
License-File: LICENSE
|
|
49
|
+
Provides-Extra: dev
|
|
50
|
+
Requires-Dist: pytest>=7; extra == "dev"
|
|
51
|
+
Requires-Dist: ruff>=0.4; extra == "dev"
|
|
52
|
+
Dynamic: license-file
|
|
53
|
+
|
|
54
|
+
# pytmrobot
|
|
55
|
+
|
|
56
|
+
**Python API for Techman (TM) Robots** — control your TM robot without writing TMScript.
|
|
57
|
+
|
|
58
|
+
[](https://www.python.org/)
|
|
59
|
+
[](LICENSE)
|
|
60
|
+
|
|
61
|
+
[繁體中文說明文件](docs/wiki.md) | [Changelog](CHANGELOG.md)
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
## Features
|
|
66
|
+
|
|
67
|
+
| Category | Capabilities |
|
|
68
|
+
|---|---|
|
|
69
|
+
| **Motion** | PTP, Line, Circle, relative moves, PVT trajectories |
|
|
70
|
+
| **I/O** | Digital / analog output & input, batch read |
|
|
71
|
+
| **State** | TCP position, joint angles, force, speed, snapshot |
|
|
72
|
+
| **Force sensing** | TouchStop, Compliance, Force control (FTSensor) |
|
|
73
|
+
| **Communication** | Modbus TCP read/write with named Presets |
|
|
74
|
+
| **Vision** | Trigger vision jobs, read output poses |
|
|
75
|
+
| **HMI** | Operator dialogs (choice + popup) |
|
|
76
|
+
| **Multi-robot** | Each `TMRobot` instance is fully independent — run 12+ in parallel |
|
|
77
|
+
|
|
78
|
+
---
|
|
79
|
+
|
|
80
|
+
## Requirements
|
|
81
|
+
|
|
82
|
+
- Python **3.10+**
|
|
83
|
+
- TM Robot running **TMflow 1.80+** with a **Listen Node** in the flow
|
|
84
|
+
- Network access to port **5890** on the robot controller
|
|
85
|
+
|
|
86
|
+
No external dependencies — only the Python standard library.
|
|
87
|
+
|
|
88
|
+
---
|
|
89
|
+
|
|
90
|
+
## Installation
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
pip install pytmrobot
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
Or install from source:
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
git clone https://github.com/harry-techman/pytmrobot.git
|
|
100
|
+
cd pytmrobot
|
|
101
|
+
pip install -e .
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
---
|
|
105
|
+
|
|
106
|
+
## Quick Start
|
|
107
|
+
|
|
108
|
+
```python
|
|
109
|
+
from pytmrobot import TMRobot, CartPoint
|
|
110
|
+
|
|
111
|
+
with TMRobot("192.168.1.101") as robot:
|
|
112
|
+
|
|
113
|
+
home = CartPoint(400, -100, 500, 180, 0, 90) # X, Y, Z, Rx, Ry, Rz
|
|
114
|
+
pick = CartPoint(400, -100, 280, 180, 0, 90)
|
|
115
|
+
|
|
116
|
+
robot.move.ptp(home, speed=30) # point-to-point move, 30 %
|
|
117
|
+
robot.move.ptp(pick, speed=10) # slow approach
|
|
118
|
+
|
|
119
|
+
robot.io.set_do(2, True) # close gripper (DO[2] = 1)
|
|
120
|
+
robot.sleep(500) # wait 500 ms on robot side
|
|
121
|
+
|
|
122
|
+
robot.move.ptp(home, speed=30)
|
|
123
|
+
robot.io.set_do(2, False) # open gripper
|
|
124
|
+
|
|
125
|
+
pos = robot.state.tcp_position # read current TCP pose
|
|
126
|
+
print(f"Done — X={pos[0]:.1f} Y={pos[1]:.1f} Z={pos[2]:.1f} mm")
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
---
|
|
130
|
+
|
|
131
|
+
## Sub-controllers
|
|
132
|
+
|
|
133
|
+
| Property | Description |
|
|
134
|
+
|---|---|
|
|
135
|
+
| `robot.move` | PTP / Line / Circle / relative / PVT |
|
|
136
|
+
| `robot.io` | DO, AO, DI, AI, batch read |
|
|
137
|
+
| `robot.state` | TCP position, joints, force, speed, snapshot |
|
|
138
|
+
| `robot.decision` | `ask()` choice dialog, `popup()` confirmation |
|
|
139
|
+
| `robot.modbus` | Modbus TCP connect / preset / read / write |
|
|
140
|
+
| `robot.touchstop` | TouchStop — detect contact and stop |
|
|
141
|
+
| `robot.compliance` | Compliance — compliant motion until resistance |
|
|
142
|
+
| `robot.force` | Force control with external FTSensor |
|
|
143
|
+
| `robot.vision` | Trigger vision jobs, get output pose |
|
|
144
|
+
|
|
145
|
+
---
|
|
146
|
+
|
|
147
|
+
## More Examples
|
|
148
|
+
|
|
149
|
+
### Read robot state
|
|
150
|
+
|
|
151
|
+
```python
|
|
152
|
+
s = robot.state.snapshot()
|
|
153
|
+
print(s.tcp_position) # (X, Y, Z, Rx, Ry, Rz)
|
|
154
|
+
print(s.joint_angles) # (J1 … J6)
|
|
155
|
+
print(s.tcp_force_3d) # resultant force N
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
### TouchStop — find workpiece surface
|
|
159
|
+
|
|
160
|
+
```python
|
|
161
|
+
result = robot.touchstop.run(
|
|
162
|
+
direction=32, # Z− (1=X+, 2=X−, 4=Y+, 8=Y−, 16=Z+, 32=Z−)
|
|
163
|
+
distance=50.0, # max travel mm
|
|
164
|
+
force=5.0, # contact threshold N
|
|
165
|
+
speed=10,
|
|
166
|
+
)
|
|
167
|
+
if result == 5: # Resisted
|
|
168
|
+
z = robot.touchstop.get_stopped_pos()[2]
|
|
169
|
+
print(f"Surface at Z = {z:.2f} mm")
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
### Multi-robot (12 concurrent)
|
|
173
|
+
|
|
174
|
+
```python
|
|
175
|
+
from concurrent.futures import ThreadPoolExecutor
|
|
176
|
+
|
|
177
|
+
robots = [TMRobot(f"192.168.1.{100+i}") for i in range(12)]
|
|
178
|
+
for r in robots:
|
|
179
|
+
r.connect()
|
|
180
|
+
|
|
181
|
+
with ThreadPoolExecutor(max_workers=12) as pool:
|
|
182
|
+
futures = [pool.submit(run_task, r) for r in robots]
|
|
183
|
+
for f in futures:
|
|
184
|
+
f.result()
|
|
185
|
+
|
|
186
|
+
for r in robots:
|
|
187
|
+
r.disconnect()
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
### Modbus TCP
|
|
191
|
+
|
|
192
|
+
```python
|
|
193
|
+
robot.modbus.connect("192.168.1.10")
|
|
194
|
+
robot.modbus.preset("light", 1, "DO", 7206, "bool")
|
|
195
|
+
robot.modbus.write("light", True)
|
|
196
|
+
print(robot.modbus.read_bool("light"))
|
|
197
|
+
robot.modbus.disconnect()
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
### Vision-guided pick
|
|
201
|
+
|
|
202
|
+
```python
|
|
203
|
+
if robot.vision.do_job("DetectPart"):
|
|
204
|
+
pose = robot.vision.get_output_pose("DetectPart", "ArmPose_0")
|
|
205
|
+
robot.move.ptp(CartPoint(*pose), speed=20)
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
---
|
|
209
|
+
|
|
210
|
+
## Running Tests
|
|
211
|
+
|
|
212
|
+
```bash
|
|
213
|
+
pip install -e ".[dev]"
|
|
214
|
+
python -m pytest tests/ -v
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
All 259 tests run without a physical robot (mock-based unit tests).
|
|
218
|
+
|
|
219
|
+
---
|
|
220
|
+
|
|
221
|
+
## Documentation
|
|
222
|
+
|
|
223
|
+
Full API reference and tutorials (繁體中文): [`docs/wiki.md`](docs/wiki.md)
|
|
224
|
+
|
|
225
|
+
---
|
|
226
|
+
|
|
227
|
+
## License
|
|
228
|
+
|
|
229
|
+
MIT — see [LICENSE](LICENSE).
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
# pytmrobot
|
|
2
|
+
|
|
3
|
+
**Python API for Techman (TM) Robots** — control your TM robot without writing TMScript.
|
|
4
|
+
|
|
5
|
+
[](https://www.python.org/)
|
|
6
|
+
[](LICENSE)
|
|
7
|
+
|
|
8
|
+
[繁體中文說明文件](docs/wiki.md) | [Changelog](CHANGELOG.md)
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## Features
|
|
13
|
+
|
|
14
|
+
| Category | Capabilities |
|
|
15
|
+
|---|---|
|
|
16
|
+
| **Motion** | PTP, Line, Circle, relative moves, PVT trajectories |
|
|
17
|
+
| **I/O** | Digital / analog output & input, batch read |
|
|
18
|
+
| **State** | TCP position, joint angles, force, speed, snapshot |
|
|
19
|
+
| **Force sensing** | TouchStop, Compliance, Force control (FTSensor) |
|
|
20
|
+
| **Communication** | Modbus TCP read/write with named Presets |
|
|
21
|
+
| **Vision** | Trigger vision jobs, read output poses |
|
|
22
|
+
| **HMI** | Operator dialogs (choice + popup) |
|
|
23
|
+
| **Multi-robot** | Each `TMRobot` instance is fully independent — run 12+ in parallel |
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## Requirements
|
|
28
|
+
|
|
29
|
+
- Python **3.10+**
|
|
30
|
+
- TM Robot running **TMflow 1.80+** with a **Listen Node** in the flow
|
|
31
|
+
- Network access to port **5890** on the robot controller
|
|
32
|
+
|
|
33
|
+
No external dependencies — only the Python standard library.
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## Installation
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
pip install pytmrobot
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Or install from source:
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
git clone https://github.com/harry-techman/pytmrobot.git
|
|
47
|
+
cd pytmrobot
|
|
48
|
+
pip install -e .
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
## Quick Start
|
|
54
|
+
|
|
55
|
+
```python
|
|
56
|
+
from pytmrobot import TMRobot, CartPoint
|
|
57
|
+
|
|
58
|
+
with TMRobot("192.168.1.101") as robot:
|
|
59
|
+
|
|
60
|
+
home = CartPoint(400, -100, 500, 180, 0, 90) # X, Y, Z, Rx, Ry, Rz
|
|
61
|
+
pick = CartPoint(400, -100, 280, 180, 0, 90)
|
|
62
|
+
|
|
63
|
+
robot.move.ptp(home, speed=30) # point-to-point move, 30 %
|
|
64
|
+
robot.move.ptp(pick, speed=10) # slow approach
|
|
65
|
+
|
|
66
|
+
robot.io.set_do(2, True) # close gripper (DO[2] = 1)
|
|
67
|
+
robot.sleep(500) # wait 500 ms on robot side
|
|
68
|
+
|
|
69
|
+
robot.move.ptp(home, speed=30)
|
|
70
|
+
robot.io.set_do(2, False) # open gripper
|
|
71
|
+
|
|
72
|
+
pos = robot.state.tcp_position # read current TCP pose
|
|
73
|
+
print(f"Done — X={pos[0]:.1f} Y={pos[1]:.1f} Z={pos[2]:.1f} mm")
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
---
|
|
77
|
+
|
|
78
|
+
## Sub-controllers
|
|
79
|
+
|
|
80
|
+
| Property | Description |
|
|
81
|
+
|---|---|
|
|
82
|
+
| `robot.move` | PTP / Line / Circle / relative / PVT |
|
|
83
|
+
| `robot.io` | DO, AO, DI, AI, batch read |
|
|
84
|
+
| `robot.state` | TCP position, joints, force, speed, snapshot |
|
|
85
|
+
| `robot.decision` | `ask()` choice dialog, `popup()` confirmation |
|
|
86
|
+
| `robot.modbus` | Modbus TCP connect / preset / read / write |
|
|
87
|
+
| `robot.touchstop` | TouchStop — detect contact and stop |
|
|
88
|
+
| `robot.compliance` | Compliance — compliant motion until resistance |
|
|
89
|
+
| `robot.force` | Force control with external FTSensor |
|
|
90
|
+
| `robot.vision` | Trigger vision jobs, get output pose |
|
|
91
|
+
|
|
92
|
+
---
|
|
93
|
+
|
|
94
|
+
## More Examples
|
|
95
|
+
|
|
96
|
+
### Read robot state
|
|
97
|
+
|
|
98
|
+
```python
|
|
99
|
+
s = robot.state.snapshot()
|
|
100
|
+
print(s.tcp_position) # (X, Y, Z, Rx, Ry, Rz)
|
|
101
|
+
print(s.joint_angles) # (J1 … J6)
|
|
102
|
+
print(s.tcp_force_3d) # resultant force N
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### TouchStop — find workpiece surface
|
|
106
|
+
|
|
107
|
+
```python
|
|
108
|
+
result = robot.touchstop.run(
|
|
109
|
+
direction=32, # Z− (1=X+, 2=X−, 4=Y+, 8=Y−, 16=Z+, 32=Z−)
|
|
110
|
+
distance=50.0, # max travel mm
|
|
111
|
+
force=5.0, # contact threshold N
|
|
112
|
+
speed=10,
|
|
113
|
+
)
|
|
114
|
+
if result == 5: # Resisted
|
|
115
|
+
z = robot.touchstop.get_stopped_pos()[2]
|
|
116
|
+
print(f"Surface at Z = {z:.2f} mm")
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
### Multi-robot (12 concurrent)
|
|
120
|
+
|
|
121
|
+
```python
|
|
122
|
+
from concurrent.futures import ThreadPoolExecutor
|
|
123
|
+
|
|
124
|
+
robots = [TMRobot(f"192.168.1.{100+i}") for i in range(12)]
|
|
125
|
+
for r in robots:
|
|
126
|
+
r.connect()
|
|
127
|
+
|
|
128
|
+
with ThreadPoolExecutor(max_workers=12) as pool:
|
|
129
|
+
futures = [pool.submit(run_task, r) for r in robots]
|
|
130
|
+
for f in futures:
|
|
131
|
+
f.result()
|
|
132
|
+
|
|
133
|
+
for r in robots:
|
|
134
|
+
r.disconnect()
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
### Modbus TCP
|
|
138
|
+
|
|
139
|
+
```python
|
|
140
|
+
robot.modbus.connect("192.168.1.10")
|
|
141
|
+
robot.modbus.preset("light", 1, "DO", 7206, "bool")
|
|
142
|
+
robot.modbus.write("light", True)
|
|
143
|
+
print(robot.modbus.read_bool("light"))
|
|
144
|
+
robot.modbus.disconnect()
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
### Vision-guided pick
|
|
148
|
+
|
|
149
|
+
```python
|
|
150
|
+
if robot.vision.do_job("DetectPart"):
|
|
151
|
+
pose = robot.vision.get_output_pose("DetectPart", "ArmPose_0")
|
|
152
|
+
robot.move.ptp(CartPoint(*pose), speed=20)
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
---
|
|
156
|
+
|
|
157
|
+
## Running Tests
|
|
158
|
+
|
|
159
|
+
```bash
|
|
160
|
+
pip install -e ".[dev]"
|
|
161
|
+
python -m pytest tests/ -v
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
All 259 tests run without a physical robot (mock-based unit tests).
|
|
165
|
+
|
|
166
|
+
---
|
|
167
|
+
|
|
168
|
+
## Documentation
|
|
169
|
+
|
|
170
|
+
Full API reference and tutorials (繁體中文): [`docs/wiki.md`](docs/wiki.md)
|
|
171
|
+
|
|
172
|
+
---
|
|
173
|
+
|
|
174
|
+
## License
|
|
175
|
+
|
|
176
|
+
MIT — see [LICENSE](LICENSE).
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=68"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
# ── Project metadata ────────────────────────────────────────────────────────
|
|
6
|
+
|
|
7
|
+
[project]
|
|
8
|
+
name = "pytmrobot"
|
|
9
|
+
version = "0.1.0"
|
|
10
|
+
description = "Python API for controlling Techman (TM) robots via Listen Node — no TMScript required"
|
|
11
|
+
readme = "README.md"
|
|
12
|
+
license = { file = "LICENSE" }
|
|
13
|
+
requires-python = ">=3.10"
|
|
14
|
+
authors = [{ name = "Harry" }]
|
|
15
|
+
keywords = [
|
|
16
|
+
"robot", "techman", "TM robot", "collaborative robot", "cobot",
|
|
17
|
+
"industrial automation", "TMScript", "Listen Node",
|
|
18
|
+
]
|
|
19
|
+
classifiers = [
|
|
20
|
+
"Development Status :: 3 - Alpha",
|
|
21
|
+
"Intended Audience :: Developers",
|
|
22
|
+
"Intended Audience :: Manufacturing",
|
|
23
|
+
"License :: OSI Approved :: MIT License",
|
|
24
|
+
"Operating System :: OS Independent",
|
|
25
|
+
"Programming Language :: Python :: 3",
|
|
26
|
+
"Programming Language :: Python :: 3.10",
|
|
27
|
+
"Programming Language :: Python :: 3.11",
|
|
28
|
+
"Programming Language :: Python :: 3.12",
|
|
29
|
+
"Topic :: Scientific/Engineering",
|
|
30
|
+
"Topic :: System :: Hardware",
|
|
31
|
+
"Typing :: Typed",
|
|
32
|
+
]
|
|
33
|
+
|
|
34
|
+
# 無任何執行期依賴,僅需標準函式庫
|
|
35
|
+
dependencies = []
|
|
36
|
+
|
|
37
|
+
[project.urls]
|
|
38
|
+
Homepage = "https://github.com/harry123180/TMDemo"
|
|
39
|
+
Documentation = "https://github.com/harry123180/TMDemo/blob/master/docs/wiki.md"
|
|
40
|
+
Repository = "https://github.com/harry123180/TMDemo"
|
|
41
|
+
"Bug Tracker" = "https://github.com/harry123180/TMDemo/issues"
|
|
42
|
+
Changelog = "https://github.com/harry123180/TMDemo/blob/master/CHANGELOG.md"
|
|
43
|
+
|
|
44
|
+
[project.optional-dependencies]
|
|
45
|
+
dev = [
|
|
46
|
+
"pytest>=7",
|
|
47
|
+
"ruff>=0.4",
|
|
48
|
+
]
|
|
49
|
+
|
|
50
|
+
# ── Package discovery ───────────────────────────────────────────────────────
|
|
51
|
+
|
|
52
|
+
[tool.setuptools.packages.find]
|
|
53
|
+
include = ["pytmrobot*"]
|
|
54
|
+
|
|
55
|
+
[tool.setuptools.package-data]
|
|
56
|
+
pytmrobot = ["py.typed"] # PEP 561 — 告知 mypy/pyright 本套件有 type hints
|
|
57
|
+
|
|
58
|
+
# ── pytest ──────────────────────────────────────────────────────────────────
|
|
59
|
+
|
|
60
|
+
[tool.pytest.ini_options]
|
|
61
|
+
testpaths = ["tests"]
|
|
62
|
+
addopts = "-q"
|
|
63
|
+
|
|
64
|
+
# ── ruff(lint + format)────────────────────────────────────────────────────
|
|
65
|
+
|
|
66
|
+
[tool.ruff]
|
|
67
|
+
line-length = 100
|
|
68
|
+
target-version = "py310"
|
|
69
|
+
exclude = [
|
|
70
|
+
".git", "__pycache__", ".pytest_cache",
|
|
71
|
+
"chapters/", "examples/",
|
|
72
|
+
]
|
|
73
|
+
|
|
74
|
+
[tool.ruff.lint]
|
|
75
|
+
# E/W = pycodestyle F = pyflakes I = isort UP = pyupgrade B = flake8-bugbear
|
|
76
|
+
select = ["E", "W", "F", "I", "UP", "B"]
|
|
77
|
+
ignore = [
|
|
78
|
+
"E501", # line too long — 長字串 TMScript 不切割
|
|
79
|
+
"B008", # do not perform function calls in argument defaults
|
|
80
|
+
"UP006", # use `type` instead of `Type` — 兼容 3.10 TYPE_CHECKING 用法
|
|
81
|
+
"UP007", # use `X | Y` — 保留 Union 在 TYPE_CHECKING 區塊
|
|
82
|
+
]
|
|
83
|
+
|
|
84
|
+
[tool.ruff.lint.isort]
|
|
85
|
+
known-first-party = ["pytmrobot"]
|
|
86
|
+
|
|
87
|
+
[tool.ruff.format]
|
|
88
|
+
quote-style = "double"
|
|
89
|
+
indent-style = "space"
|
|
90
|
+
|
|
91
|
+
# ── mypy(選用,嚴格模式)──────────────────────────────────────────────────
|
|
92
|
+
|
|
93
|
+
[tool.mypy]
|
|
94
|
+
python_version = "3.10"
|
|
95
|
+
strict = false
|
|
96
|
+
ignore_missing_imports = true
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
"""
|
|
2
|
+
pytmrobot — Python TM Robot 控制函式庫
|
|
3
|
+
|
|
4
|
+
讓 Python 開發者無需了解 TMScript,直接以 Pythonic API 控制達明機器人。
|
|
5
|
+
|
|
6
|
+
Quick Start::
|
|
7
|
+
|
|
8
|
+
from pytmrobot import TMRobot, CartPoint
|
|
9
|
+
|
|
10
|
+
with TMRobot("192.168.1.101") as robot:
|
|
11
|
+
home = CartPoint(400, -100, 500, 180, 0, 90)
|
|
12
|
+
pick = CartPoint(400, -100, 280, 180, 0, 90)
|
|
13
|
+
|
|
14
|
+
robot.move.ptp(home, speed=30)
|
|
15
|
+
robot.move.ptp(pick, speed=10)
|
|
16
|
+
robot.io.set_do(2, True) # 夾爪閉合
|
|
17
|
+
robot.sleep(500)
|
|
18
|
+
robot.move.ptp(home, speed=30)
|
|
19
|
+
robot.io.set_do(2, False) # 夾爪張開
|
|
20
|
+
|
|
21
|
+
pos = robot.state.tcp_position
|
|
22
|
+
print(f"完成!位置: X={pos[0]:.2f}, Y={pos[1]:.2f}, Z={pos[2]:.2f}")
|
|
23
|
+
|
|
24
|
+
Public API
|
|
25
|
+
----------
|
|
26
|
+
主類別:
|
|
27
|
+
TMRobot 控制機器人的主要入口(支援 context manager)
|
|
28
|
+
|
|
29
|
+
點位型別:
|
|
30
|
+
CartPoint 笛卡爾座標目標點 (X, Y, Z, Rx, Ry, Rz)
|
|
31
|
+
JointPoint 關節角度目標點 (J1, J2, J3, J4, J5, J6)
|
|
32
|
+
|
|
33
|
+
列舉:
|
|
34
|
+
SpeedUnit 直線/圓弧速度單位 (PERCENT / ABS_SYNC / ABS_LOCK)
|
|
35
|
+
BlendUnit 軌跡混合單位 (PERCENT / RADIUS)
|
|
36
|
+
|
|
37
|
+
資料容器:
|
|
38
|
+
RobotState robot.state.snapshot() 的回傳型別
|
|
39
|
+
IOState robot.io.get_all_io() 的回傳型別
|
|
40
|
+
|
|
41
|
+
例外:
|
|
42
|
+
TMError 所有例外的基礎類別
|
|
43
|
+
TMConnectionError 連線失敗
|
|
44
|
+
TMScriptError 機器人回傳 ERROR
|
|
45
|
+
TMTimeoutError 等待逾時
|
|
46
|
+
TMValueError 參數超出範圍
|
|
47
|
+
"""
|
|
48
|
+
|
|
49
|
+
from .exceptions import (
|
|
50
|
+
TMConnectionError,
|
|
51
|
+
TMError,
|
|
52
|
+
TMScriptError,
|
|
53
|
+
TMTimeoutError,
|
|
54
|
+
TMValueError,
|
|
55
|
+
)
|
|
56
|
+
from .robot import TMRobot
|
|
57
|
+
from .types import (
|
|
58
|
+
BlendUnit,
|
|
59
|
+
CartPoint,
|
|
60
|
+
IOState,
|
|
61
|
+
JointPoint,
|
|
62
|
+
Pose6,
|
|
63
|
+
RobotState,
|
|
64
|
+
SpeedUnit,
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
__version__ = "0.1.0"
|
|
68
|
+
__author__ = "TMDemo Contributors"
|
|
69
|
+
|
|
70
|
+
__all__ = [
|
|
71
|
+
# 主類別
|
|
72
|
+
"TMRobot",
|
|
73
|
+
# 點位型別
|
|
74
|
+
"CartPoint",
|
|
75
|
+
"JointPoint",
|
|
76
|
+
"Pose6",
|
|
77
|
+
# 列舉
|
|
78
|
+
"SpeedUnit",
|
|
79
|
+
"BlendUnit",
|
|
80
|
+
# 資料容器
|
|
81
|
+
"RobotState",
|
|
82
|
+
"IOState",
|
|
83
|
+
# 例外
|
|
84
|
+
"TMError",
|
|
85
|
+
"TMConnectionError",
|
|
86
|
+
"TMScriptError",
|
|
87
|
+
"TMTimeoutError",
|
|
88
|
+
"TMValueError",
|
|
89
|
+
]
|