openarm-sdk 0.1.0__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.
@@ -0,0 +1,191 @@
1
+ """Public API for the OpenArm Python SDK."""
2
+
3
+ from .client import OpenArmClient
4
+ from .end_effectors import EndEffectorClient
5
+ from .teleop import TeleopClient
6
+ from .joint_servo import JointServoClient, JointServoSession
7
+ from .enums import (
8
+ Arm,
9
+ CartesianAxis,
10
+ DependencyKind,
11
+ EndEffectorOperation,
12
+ EndEffectorType,
13
+ FaultSeverity,
14
+ HealthServingStatus,
15
+ JogDirection,
16
+ JogSessionState,
17
+ JogStopReason,
18
+ JogType,
19
+ MotorFaultFlag,
20
+ MotionExecutionMode,
21
+ MotionTaskState,
22
+ MotionTaskType,
23
+ OperationMode,
24
+ PositionUnit,
25
+ ReadinessState,
26
+ RecordingState,
27
+ RecordingSource,
28
+ TeleopSource,
29
+ TeleopState,
30
+ JointServoState,
31
+ QnBotControlMode,
32
+ QnBotGripperControlMode,
33
+ )
34
+ from .jog import JogClient, JogSessionHandle
35
+ from .joint_parameters import JointParametersClient
36
+ from .mode import ModeClient
37
+ from .safety import SafetyClient
38
+ from .recording import RecordingClient
39
+ from .errors import (
40
+ ClientClosedError,
41
+ IncompatibleServerError,
42
+ OpenArmError,
43
+ OpenArmOperationError,
44
+ ProtocolError,
45
+ ResourceExhaustedError,
46
+ RpcTimeoutError,
47
+ RpcTransportError,
48
+ TeleopOperationError,
49
+ )
50
+ from .models import (
51
+ CapabilityStatus,
52
+ ArmHardwareState,
53
+ ArmJointParameters,
54
+ JointParameters,
55
+ JointGains,
56
+ RecordingInfo,
57
+ RecordingKeypoint,
58
+ RecordingSegment,
59
+ RecordingTimelineItem,
60
+ RecordingImportResult,
61
+ RecordingCsvChunk,
62
+ EmergencyStopState,
63
+ CartesianPose,
64
+ CartesianPosition,
65
+ ControllerStatus,
66
+ DependencyStatus,
67
+ EndEffectorPose,
68
+ EndEffectorPoseSnapshot,
69
+ EndEffectorInfo,
70
+ EndEffectorInfoSnapshot,
71
+ EndEffectorOperationCapability,
72
+ EndEffectorState,
73
+ EndEffectorStateSnapshot,
74
+ JointState,
75
+ JogSession,
76
+ JogStopResult,
77
+ MotorStatus,
78
+ MotorStatusSnapshot,
79
+ MotionCommandResult,
80
+ MotionTask,
81
+ MotionTaskWaitResult,
82
+ OperationResult,
83
+ Quaternion,
84
+ ServerInfo,
85
+ SystemArmStatus,
86
+ SystemFault,
87
+ SystemStatus,
88
+ SystemTeleoperationStatus,
89
+ TeleopSourceStatus,
90
+ JointServoFeedback,
91
+ TeleopManagerStatus,
92
+ TeleopManagerResult,
93
+ TeleopRunningStatus,
94
+ QnBotScalingAndOffset,
95
+ QnBotTeleopConfig,
96
+ )
97
+
98
+ __all__ = [
99
+ "JointServoClient",
100
+ "JointServoSession",
101
+ "JointServoState",
102
+ "JointServoFeedback",
103
+ "TeleopClient",
104
+ "TeleopSource",
105
+ "TeleopState",
106
+ "TeleopSourceStatus",
107
+ "TeleopManagerStatus",
108
+ "TeleopManagerResult",
109
+ "TeleopRunningStatus",
110
+ "TeleopOperationError",
111
+ "QnBotControlMode",
112
+ "QnBotGripperControlMode",
113
+ "QnBotScalingAndOffset",
114
+ "QnBotTeleopConfig",
115
+ "Arm",
116
+ "RecordingClient",
117
+ "RecordingState",
118
+ "RecordingSource",
119
+ "RecordingInfo",
120
+ "RecordingKeypoint",
121
+ "RecordingSegment",
122
+ "RecordingTimelineItem",
123
+ "RecordingImportResult",
124
+ "RecordingCsvChunk",
125
+ "ArmHardwareState",
126
+ "ArmJointParameters",
127
+ "JointParameters",
128
+ "JointParametersClient",
129
+ "JointGains",
130
+ "EmergencyStopState",
131
+ "SafetyClient",
132
+ "CapabilityStatus",
133
+ "CartesianPose",
134
+ "CartesianPosition",
135
+ "CartesianAxis",
136
+ "ClientClosedError",
137
+ "ControllerStatus",
138
+ "DependencyKind",
139
+ "DependencyStatus",
140
+ "EndEffectorPose",
141
+ "EndEffectorPoseSnapshot",
142
+ "EndEffectorClient",
143
+ "EndEffectorInfo",
144
+ "EndEffectorInfoSnapshot",
145
+ "EndEffectorOperation",
146
+ "EndEffectorOperationCapability",
147
+ "EndEffectorState",
148
+ "EndEffectorStateSnapshot",
149
+ "EndEffectorType",
150
+ "FaultSeverity",
151
+ "HealthServingStatus",
152
+ "IncompatibleServerError",
153
+ "JogClient",
154
+ "JogDirection",
155
+ "JogSession",
156
+ "JogSessionHandle",
157
+ "JogSessionState",
158
+ "JogStopReason",
159
+ "JogStopResult",
160
+ "JogType",
161
+ "JointState",
162
+ "MotorFaultFlag",
163
+ "MotorStatus",
164
+ "MotorStatusSnapshot",
165
+ "MotionCommandResult",
166
+ "MotionExecutionMode",
167
+ "MotionTask",
168
+ "MotionTaskState",
169
+ "MotionTaskType",
170
+ "MotionTaskWaitResult",
171
+ "ModeClient",
172
+ "OpenArmClient",
173
+ "OpenArmError",
174
+ "OpenArmOperationError",
175
+ "OperationResult",
176
+ "OperationMode",
177
+ "PositionUnit",
178
+ "ProtocolError",
179
+ "ReadinessState",
180
+ "Quaternion",
181
+ "ResourceExhaustedError",
182
+ "RpcTimeoutError",
183
+ "RpcTransportError",
184
+ "ServerInfo",
185
+ "SystemArmStatus",
186
+ "SystemFault",
187
+ "SystemStatus",
188
+ "SystemTeleoperationStatus",
189
+ ]
190
+
191
+ __version__ = "0.1.0"
@@ -0,0 +1 @@
1
+ """Internal SDK helpers; not part of the public API."""
@@ -0,0 +1,202 @@
1
+ """Shared validation helpers."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import math
6
+
7
+ from ..enums import Arm
8
+
9
+
10
+ def validate_timeout(timeout: float | None, *, name: str = "timeout") -> None:
11
+ """校验 RPC 超时时间,允许使用 None 取消 deadline。
12
+
13
+ 参数:
14
+ timeout: 本次 gRPC deadline,单位秒;None 表示不设置 deadline。
15
+ name: 字段或参数名称,用于读取对应字段或生成错误信息。
16
+
17
+ 原有说明:
18
+ Validate a gRPC timeout while allowing None for no deadline.
19
+ """
20
+
21
+ if timeout is None:
22
+ return
23
+ if isinstance(timeout, bool) or not isinstance(timeout, (int, float)):
24
+ raise TypeError(f"{name} must be a positive finite number or None")
25
+ if not math.isfinite(timeout) or timeout <= 0:
26
+ raise ValueError(f"{name} must be a positive finite number or None")
27
+
28
+
29
+ def encode_arm(arm: Arm, *, allow_both: bool = True) -> int:
30
+ """校验机械臂枚举并转换为协议中的机械臂编号。
31
+
32
+ 参数:
33
+ arm: 机械臂枚举 Arm.LEFT、Arm.RIGHT 或 Arm.BOTH,BOTH 在协议中编码为 0。
34
+ allow_both: 是否允许把 Arm.BOTH 作为本次请求目标。
35
+
36
+ 原有说明:
37
+ Validate a public Arm and return its current protobuf wire value.
38
+ """
39
+
40
+ if not isinstance(arm, Arm):
41
+ raise TypeError("arm must be an openarm_sdk.Arm value")
42
+ if arm is Arm.UNKNOWN:
43
+ raise ValueError("Arm.UNKNOWN cannot be sent to RCG")
44
+ if not allow_both and arm is Arm.BOTH:
45
+ raise ValueError("Arm.BOTH is not allowed for this operation")
46
+ return int(arm)
47
+
48
+
49
+ def validate_rate_hz(rate_hz: int, *, maximum: int) -> None:
50
+ """校验订阅频率的整数类型和上限,0 表示由服务端选择默认频率。
51
+
52
+ 参数:
53
+ rate_hz: 请求订阅频率,单位 Hz,允许 0~100 的整数;0 选择服务端默认。
54
+ maximum: 允许的频率上限,单位 Hz。
55
+
56
+ 原有说明:
57
+ Validate a requested polling rate, where zero selects the default.
58
+ """
59
+
60
+ if isinstance(rate_hz, bool) or not isinstance(rate_hz, int):
61
+ raise TypeError("rate_hz must be an integer")
62
+ if rate_hz < 0 or rate_hz > maximum:
63
+ raise ValueError(f"rate_hz must be between 0 and {maximum}")
64
+
65
+
66
+ def validate_percent(value: int, *, name: str, allow_zero: bool = True) -> int:
67
+ """校验控制参数是否为允许范围内的整数百分比。
68
+
69
+ 参数:
70
+ value: 待校验的整数百分比数值。
71
+ name: 字段或参数名称,用于读取对应字段或生成错误信息。
72
+ allow_zero: 百分比校验是否允许取 0;False 时最小值为 1。
73
+
74
+ 原有说明:
75
+ Validate an integer percentage used by the current motion contract.
76
+ """
77
+
78
+ minimum = 0 if allow_zero else 1
79
+ if isinstance(value, bool) or not isinstance(value, int):
80
+ raise TypeError(f"{name} must be an integer")
81
+ if value < minimum or value > 100:
82
+ raise ValueError(f"{name} must be between {minimum} and 100")
83
+ return value
84
+
85
+
86
+ def validate_finite_values(
87
+ values: object, *, name: str, length: int
88
+ ) -> tuple[float, ...]:
89
+ """校验定长数值序列并转换为有限浮点数元组。
90
+
91
+ 参数:
92
+ values: 需要校验或转换的输入值序列。
93
+ name: 字段或参数名称,用于读取对应字段或生成错误信息。
94
+ length: 要求的序列元素数量。
95
+
96
+ 原有说明:
97
+ Validate a fixed-size numeric sequence and return normalized floats.
98
+ """
99
+
100
+ if isinstance(values, (str, bytes)):
101
+ raise TypeError(f"{name} must be a sequence of numbers")
102
+ try:
103
+ raw_values = tuple(values) # type: ignore[arg-type]
104
+ except TypeError as error:
105
+ raise TypeError(f"{name} must be a sequence of numbers") from error
106
+ if any(isinstance(value, bool) for value in raw_values):
107
+ raise TypeError(f"{name} must not contain bool values")
108
+ try:
109
+ normalized = tuple(float(value) for value in raw_values)
110
+ except (TypeError, ValueError) as error:
111
+ raise TypeError(f"{name} must be a sequence of numbers") from error
112
+ if len(normalized) != length:
113
+ raise ValueError(f"{name} must contain exactly {length} values")
114
+ if not all(math.isfinite(value) for value in normalized):
115
+ raise ValueError(f"{name} values must all be finite")
116
+ return normalized
117
+
118
+
119
+ def validate_finite_sequence(
120
+ values: object, *, name: str, allow_empty: bool = False
121
+ ) -> tuple[float, ...]:
122
+ """校验可变长度数值序列并转换为有限浮点数元组。
123
+
124
+ 参数:
125
+ values: 需要校验或转换的输入值序列。
126
+ name: 字段或参数名称,用于读取对应字段或生成错误信息。
127
+ allow_empty: 是否允许空序列;True 不豁免非空序列的数值检查。
128
+
129
+ 原有说明:
130
+ Validate a finite numeric sequence of dynamic length.
131
+ """
132
+
133
+ if isinstance(values, (str, bytes)):
134
+ raise TypeError(f"{name} must be a sequence of numbers")
135
+ try:
136
+ raw_values = tuple(values) # type: ignore[arg-type]
137
+ except TypeError as error:
138
+ raise TypeError(f"{name} must be a sequence of numbers") from error
139
+ if not allow_empty and not raw_values:
140
+ raise ValueError(f"{name} must not be empty")
141
+ if any(isinstance(value, bool) for value in raw_values):
142
+ raise TypeError(f"{name} must not contain bool values")
143
+ try:
144
+ normalized = tuple(float(value) for value in raw_values)
145
+ except (TypeError, ValueError) as error:
146
+ raise TypeError(f"{name} must be a sequence of numbers") from error
147
+ if not all(math.isfinite(value) for value in normalized):
148
+ raise ValueError(f"{name} values must all be finite")
149
+ return normalized
150
+
151
+
152
+ def validate_identifier(value: str, *, name: str) -> str:
153
+ """校验资源标识是否为非空字符串。
154
+
155
+ 参数:
156
+ value: 待校验的资源标识或文本字段值。
157
+ name: 字段或参数名称,用于读取对应字段或生成错误信息。
158
+
159
+ 原有说明:
160
+ Validate a non-empty opaque server identifier.
161
+ """
162
+
163
+ if not isinstance(value, str):
164
+ raise TypeError(f"{name} must be a string")
165
+ if not value.strip():
166
+ raise ValueError(f"{name} must not be empty")
167
+ return value
168
+
169
+
170
+ def validate_uint32(value: int, *, name: str) -> int:
171
+ """校验无符号 32 位整数,拒绝布尔值及越界值。
172
+
173
+ 参数:
174
+ value: 需要校验、转换或编码的单个输入值。
175
+ name: 字段或参数名称,用于读取对应字段或生成错误信息。
176
+
177
+ 原有说明:
178
+ Validate a protobuf uint32 value without accepting bool.
179
+ """
180
+
181
+ if isinstance(value, bool) or not isinstance(value, int):
182
+ raise TypeError(f"{name} must be an integer")
183
+ if value < 0 or value > 0xFFFFFFFF:
184
+ raise ValueError(f"{name} must be between 0 and 4294967295")
185
+ return value
186
+
187
+
188
+ def validate_joint_id(joint_id: int) -> int:
189
+ """校验从 0 开始的手臂关节索引,合法范围为 0~6。
190
+
191
+ 参数:
192
+ joint_id: 手臂关节的零起始索引,普通单关节操作要求 0~6。
193
+
194
+ 原有说明:
195
+ Validate a zero-based OpenArm arm-joint index.
196
+ """
197
+
198
+ if isinstance(joint_id, bool) or not isinstance(joint_id, int):
199
+ raise TypeError("joint_id must be an integer")
200
+ if joint_id < 0 or joint_id > 6:
201
+ raise ValueError("joint_id must be between 0 and 6")
202
+ return joint_id