litegrip-python 1.1.2__py3-none-any.whl

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.
litegrip/__init__.py ADDED
@@ -0,0 +1,298 @@
1
+ """LiteGrip SDK — self-contained gripper library for the LiteGrip adaptive
2
+ two-finger hand.
3
+
4
+ Built on the Damiao motor MIT protocol over SocketCAN. Zero dependencies
5
+ outside Python's standard library + Linux SocketCAN — no damiao_socketcan
6
+ or robot-arm libraries required.
7
+
8
+ Quick start::
9
+
10
+ from litegrip import LiteGrip
11
+
12
+ with LiteGrip(channel="can0", can_id=0x08) as gripper:
13
+ gripper.enable() # retries until the status frame says err == 1
14
+ gripper.open()
15
+ gripper.grasp(force_n=20.0, hold_s=3.0)
16
+ state = gripper.get_state()
17
+ print(state)
18
+
19
+ Subpackages
20
+ -----------
21
+ - ``litegrip.can`` — Raw SocketCAN transport + DM motor protocol codec.
22
+ Use directly if you need fine-grained control or multi-motor setups.
23
+ """
24
+
25
+ # Version reported when no ``litegrip-python`` distribution is installed in reach at all —
26
+ # no wheel, no editable install, nothing in ``site-packages``/``dist-packages``.
27
+ # The ``+`` local segment keeps it valid PEP 440 and makes it obvious in a bug
28
+ # report that nobody is looking at an official build.
29
+ _VERSION_SOURCE_TREE = "0.0.0+source"
30
+
31
+
32
+ def _detect_version(dist_name: str = "litegrip-python") -> str:
33
+ """Report the installed distribution's version, or a marker for a bare machine.
34
+
35
+ The repository never commits a version back (AGENTS.md §3): semantic-release
36
+ derives it from the commit prefixes and writes it only into the publish
37
+ workspace, so the git tag is the single source of truth. A literal
38
+ ``__version__`` in this file would therefore be a second, permanently stale
39
+ copy of that number. Reading the installed metadata instead keeps whatever the
40
+ user actually installed in one place.
41
+
42
+ Returns:
43
+ The installed distribution version, or ``"0.0.0+source"`` when no
44
+ ``litegrip-python`` distribution is installed at all. The marker is about what
45
+ is installed, not about where this file came from: a module loaded out of
46
+ the source tree still reports an installed copy's version, and the two
47
+ spells of "not the released build" are told apart by the module path, not
48
+ by the number.
49
+ """
50
+ from importlib.metadata import PackageNotFoundError, version
51
+
52
+ try:
53
+ return version(dist_name)
54
+ except PackageNotFoundError:
55
+ return _VERSION_SOURCE_TREE
56
+
57
+
58
+ __version__ = _detect_version()
59
+
60
+ # This package deliberately installs no handler and does not call
61
+ # ``logging.disable()``: a WARNING such as "this calibration file belongs to
62
+ # another channel" is a safety signal, and must reach the user even when the
63
+ # embedding program never configured logging. With no handler, Python's
64
+ # ``logging.lastResort`` prints WARNING and above to stderr. Applications that
65
+ # want to capture the records can still attach their own handler to the
66
+ # ``litegrip`` logger.
67
+
68
+ # ── High-level API ──────────────────────────────────────────────────────
69
+ from .gripper import (LiteGrip, DEFAULT_CALIB, CALIB_TEMPLATES,
70
+ default_calib_path, list_templates)
71
+
72
+ # ── Motion actions ──────────────────────────────────────────────────────
73
+ from .actions import (
74
+ MotionConfig,
75
+ MoveProgress,
76
+ MoveResult,
77
+ GraspResult,
78
+ HoldResult,
79
+ EnableResult,
80
+ WriteZeroResult,
81
+ GripperActions,
82
+ closing_travel_excursion_rad,
83
+ limit_target,
84
+ press_target,
85
+ work_limit_target,
86
+ clamp_to_travel,
87
+ force_approach_terms,
88
+ )
89
+
90
+ # ── Data models ─────────────────────────────────────────────────────────
91
+ from .models import (
92
+ STALE_AFTER_S,
93
+ GripperState,
94
+ GripperConfig,
95
+ GripperInfo,
96
+ GripperStatus,
97
+ GripperMode,
98
+ CalibrationData,
99
+ )
100
+
101
+ # ── Constants & enums ───────────────────────────────────────────────────
102
+ from .constants import (
103
+ GripperGeometry,
104
+ GripperParams,
105
+ UnitConversion,
106
+ ErrorCode,
107
+ DefaultParams,
108
+ describe_error,
109
+ DM_Motor_Type,
110
+ Control_Mode,
111
+ )
112
+
113
+ # ── Exceptions ──────────────────────────────────────────────────────────
114
+ from .exceptions import (
115
+ LiteGripError,
116
+ CommError,
117
+ ConnectError,
118
+ CommandError,
119
+ CANTimeoutError,
120
+ HardwareError,
121
+ NotInitializedError,
122
+ )
123
+
124
+ # ── Teleoperation (leader / follower) ───────────────────────────────────
125
+ from .teleop import (
126
+ GripperTeleop,
127
+ TeleopTransport,
128
+ TeleopSubscription,
129
+ UdpTeleopTransport,
130
+ InProcTeleopTransport,
131
+ TeleopError,
132
+ TeleopBusyError,
133
+ TeleopNotActiveError,
134
+ TeleopNotReady,
135
+ check_ready,
136
+ clamp_to_calibrated,
137
+ DEFAULT_GRIP_ID,
138
+ DEFAULT_GRIP_PORT,
139
+ DEFAULT_DQ_MAX,
140
+ DEFAULT_ALIGN_SPEED_MM_S,
141
+ DEFAULT_LEAD_CAP_MM,
142
+ DEFAULT_TORQUE_LIMIT_NM,
143
+ DEFAULT_READY_TOLERANCE_MM,
144
+ DEFAULT_READY_PERIOD_S,
145
+ DEFAULT_READY_TIMEOUT_S,
146
+ FRAME_SIZE,
147
+ READY_FRAME_SIZE,
148
+ encode_frame,
149
+ decode_frame,
150
+ encode_ready_frame,
151
+ decode_ready_frame,
152
+ teleop_topic,
153
+ ready_topic,
154
+ )
155
+
156
+ # ── Trajectory record and replay ────────────────────────────────────────
157
+ from .trajectory import (
158
+ Trajectory,
159
+ TrajectorySample,
160
+ TrajectoryRecorder,
161
+ TrajectoryPlayer,
162
+ trajectory_dir,
163
+ resolve_path,
164
+ DEFAULT_RATE_HZ,
165
+ TrajectoryError,
166
+ TrajectoryBusyError,
167
+ TrajectoryNotActiveError,
168
+ TrajectoryEmptyError,
169
+ TrajectoryRecordingError,
170
+ TrajectoryFormatError,
171
+ )
172
+
173
+ # ── CAN subpackage (expert) ─────────────────────────────────────────────
174
+ from . import can
175
+
176
+
177
+ # The zenoh link needs the optional ``zenoh`` dependency, so it is resolved on
178
+ # first access rather than at import time: ``import litegrip`` must work on a
179
+ # bare robot controller that will never teleoperate. Install the extra with
180
+ # ``pip install litegrip-python[zenoh]``.
181
+ _ZENOH_EXPORTS = frozenset(
182
+ {"ZenohTeleopTransport", "Listener", "Connector", "LatestSlot"})
183
+
184
+
185
+ def __getattr__(name: str):
186
+ if name in _ZENOH_EXPORTS:
187
+ try:
188
+ from . import zenoh_link
189
+ except ImportError as e:
190
+ raise ImportError(
191
+ f"litegrip.{name} needs the optional zenoh dependency — install "
192
+ "it with `pip install litegrip-python[zenoh]`") from e
193
+ return getattr(zenoh_link, name)
194
+ raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
195
+
196
+
197
+ def __dir__():
198
+ return sorted(set(globals()) | _ZENOH_EXPORTS)
199
+
200
+ __all__ = [
201
+ "__version__",
202
+ # High-level
203
+ "LiteGrip",
204
+ "DEFAULT_CALIB",
205
+ "CALIB_TEMPLATES",
206
+ "default_calib_path",
207
+ "list_templates",
208
+ # Motion actions
209
+ "MotionConfig",
210
+ "MoveProgress",
211
+ "MoveResult",
212
+ "GraspResult",
213
+ "HoldResult",
214
+ "EnableResult",
215
+ "WriteZeroResult",
216
+ "GripperActions",
217
+ "closing_travel_excursion_rad",
218
+ "limit_target",
219
+ "press_target",
220
+ "work_limit_target",
221
+ "clamp_to_travel",
222
+ "force_approach_terms",
223
+ # Models
224
+ "STALE_AFTER_S",
225
+ "GripperState",
226
+ "GripperConfig",
227
+ "GripperInfo",
228
+ "GripperStatus",
229
+ "GripperMode",
230
+ "CalibrationData",
231
+ # Constants
232
+ "GripperGeometry",
233
+ "GripperParams",
234
+ "UnitConversion",
235
+ "ErrorCode",
236
+ "DefaultParams",
237
+ "describe_error",
238
+ "DM_Motor_Type",
239
+ "Control_Mode",
240
+ # Exceptions
241
+ "LiteGripError",
242
+ "CommError",
243
+ "ConnectError",
244
+ "CommandError",
245
+ "CANTimeoutError",
246
+ "HardwareError",
247
+ "NotInitializedError",
248
+ # Teleoperation
249
+ "GripperTeleop",
250
+ "TeleopTransport",
251
+ "TeleopSubscription",
252
+ "UdpTeleopTransport",
253
+ "InProcTeleopTransport",
254
+ "TeleopError",
255
+ "TeleopBusyError",
256
+ "TeleopNotActiveError",
257
+ "TeleopNotReady",
258
+ "check_ready",
259
+ "clamp_to_calibrated",
260
+ "DEFAULT_GRIP_ID",
261
+ "DEFAULT_GRIP_PORT",
262
+ "DEFAULT_DQ_MAX",
263
+ "DEFAULT_ALIGN_SPEED_MM_S",
264
+ "DEFAULT_LEAD_CAP_MM",
265
+ "DEFAULT_TORQUE_LIMIT_NM",
266
+ "DEFAULT_READY_TOLERANCE_MM",
267
+ "DEFAULT_READY_PERIOD_S",
268
+ "DEFAULT_READY_TIMEOUT_S",
269
+ "FRAME_SIZE",
270
+ "READY_FRAME_SIZE",
271
+ "encode_frame",
272
+ "decode_frame",
273
+ "encode_ready_frame",
274
+ "decode_ready_frame",
275
+ "teleop_topic",
276
+ "ready_topic",
277
+ # Teleoperation — zenoh link (resolved lazily; needs litegrip-python[zenoh])
278
+ "ZenohTeleopTransport",
279
+ "Listener",
280
+ "Connector",
281
+ "LatestSlot",
282
+ # Trajectory record and replay
283
+ "Trajectory",
284
+ "TrajectorySample",
285
+ "TrajectoryRecorder",
286
+ "TrajectoryPlayer",
287
+ "trajectory_dir",
288
+ "resolve_path",
289
+ "DEFAULT_RATE_HZ",
290
+ "TrajectoryError",
291
+ "TrajectoryBusyError",
292
+ "TrajectoryNotActiveError",
293
+ "TrajectoryEmptyError",
294
+ "TrajectoryRecordingError",
295
+ "TrajectoryFormatError",
296
+ # Subpackages
297
+ "can",
298
+ ]