akai-transform 0.0.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.
Files changed (44) hide show
  1. akai_transform-0.0.1/CLAUDE.md +301 -0
  2. akai_transform-0.0.1/MANIFEST.in +5 -0
  3. akai_transform-0.0.1/PKG-INFO +127 -0
  4. akai_transform-0.0.1/README.md +100 -0
  5. akai_transform-0.0.1/akai_transform/__init__.py +31 -0
  6. akai_transform-0.0.1/akai_transform/const.py +51 -0
  7. akai_transform-0.0.1/akai_transform/log_quat.py +84 -0
  8. akai_transform-0.0.1/akai_transform/quat.py +447 -0
  9. akai_transform-0.0.1/akai_transform/se3.py +260 -0
  10. akai_transform-0.0.1/akai_transform/tf2d.py +170 -0
  11. akai_transform-0.0.1/akai_transform/tf3d.py +742 -0
  12. akai_transform-0.0.1/akai_transform.egg-info/PKG-INFO +127 -0
  13. akai_transform-0.0.1/akai_transform.egg-info/SOURCES.txt +42 -0
  14. akai_transform-0.0.1/akai_transform.egg-info/dependency_links.txt +1 -0
  15. akai_transform-0.0.1/akai_transform.egg-info/requires.txt +3 -0
  16. akai_transform-0.0.1/akai_transform.egg-info/top_level.txt +3 -0
  17. akai_transform-0.0.1/example//347/251/272/351/227/264/345/217/230/346/215/242/345/237/272/347/241/200/346/241/210/344/276/213(akai_transform)/01.2D/347/251/272/351/227/264/345/217/230/346/215/242/01_tf2d_/345/237/272/347/241/200/346/265/213/350/257/225.py +112 -0
  18. akai_transform-0.0.1/example//347/251/272/351/227/264/345/217/230/346/215/242/345/237/272/347/241/200/346/241/210/344/276/213(akai_transform)/01.2D/347/251/272/351/227/264/345/217/230/346/215/242/02_tf2d_/345/260/217/344/271/214/351/276/237/345/217/257/350/247/206/345/214/226.py +170 -0
  19. akai_transform-0.0.1/example//347/251/272/351/227/264/345/217/230/346/215/242/345/237/272/347/241/200/346/241/210/344/276/213(akai_transform)/02.3D/347/251/272/351/227/264/345/217/230/346/215/242(/345/237/272/347/241/200)/01_tf3d_/346/227/213/350/275/254/347/237/251/351/230/265/344/270/216/345/271/263/347/247/273/347/237/251/351/230/265.py +175 -0
  20. akai_transform-0.0.1/example//347/251/272/351/227/264/345/217/230/346/215/242/345/237/272/347/241/200/346/241/210/344/276/213(akai_transform)/02.3D/347/251/272/351/227/264/345/217/230/346/215/242(/345/237/272/347/241/200)/02_tf3d_/346/227/213/350/275/254/345/220/221/351/207/217.py +86 -0
  21. akai_transform-0.0.1/example//347/251/272/351/227/264/345/217/230/346/215/242/345/237/272/347/241/200/346/241/210/344/276/213(akai_transform)/02.3D/347/251/272/351/227/264/345/217/230/346/215/242(/345/237/272/347/241/200)/03_tf3d_/345/233/233/345/205/203/346/225/260/350/275/254/346/215/242.py +83 -0
  22. akai_transform-0.0.1/example//347/251/272/351/227/264/345/217/230/346/215/242/345/237/272/347/241/200/346/241/210/344/276/213(akai_transform)/02.3D/347/251/272/351/227/264/345/217/230/346/215/242(/345/237/272/347/241/200)/04_tf3d_XYZRPY.py +73 -0
  23. akai_transform-0.0.1/example//347/251/272/351/227/264/345/217/230/346/215/242/345/237/272/347/241/200/346/241/210/344/276/213(akai_transform)/02.3D/347/251/272/351/227/264/345/217/230/346/215/242(/345/237/272/347/241/200)/05_tf3d_Open3D/345/217/257/350/247/206/345/214/226.py +154 -0
  24. akai_transform-0.0.1/example//347/251/272/351/227/264/345/217/230/346/215/242/345/237/272/347/241/200/346/241/210/344/276/213(akai_transform)/03.3D/347/251/272/351/227/264/345/217/230/346/215/242(/350/277/233/351/230/266)/01_/344/277/256/346/255/243/347/275/227/345/276/267/351/207/214/346/240/274/346/226/257/345/217/202/346/225/260(MRP).py +64 -0
  25. akai_transform-0.0.1/example//347/251/272/351/227/264/345/217/230/346/215/242/345/237/272/347/241/200/346/241/210/344/276/213(akai_transform)/03.3D/347/251/272/351/227/264/345/217/230/346/215/242(/350/277/233/351/230/266)/02_/345/233/233/345/205/203/346/225/260/345/237/272/347/241/200/350/277/220/347/256/227.py +161 -0
  26. akai_transform-0.0.1/example//347/251/272/351/227/264/345/217/230/346/215/242/345/237/272/347/241/200/346/241/210/344/276/213(akai_transform)/03.3D/347/251/272/351/227/264/345/217/230/346/215/242(/350/277/233/351/230/266)/03_/345/257/271/346/225/260/345/233/233/345/205/203/346/225/260/350/275/254/346/215/242.py +418 -0
  27. akai_transform-0.0.1/example//347/251/272/351/227/264/345/217/230/346/215/242/345/237/272/347/241/200/346/241/210/344/276/213(akai_transform)/03.3D/347/251/272/351/227/264/345/217/230/346/215/242(/350/277/233/351/230/266)/04_/345/244/232/351/200/224/345/276/204/347/202/271/344/275/215/347/275/256/345/247/277/346/200/201/346/217/222/345/200/274_Slerp_vs_Squad.py +304 -0
  28. akai_transform-0.0.1/example//347/251/272/351/227/264/345/217/230/346/215/242/345/237/272/347/241/200/346/241/210/344/276/213(akai_transform)/04./346/235/216/347/276/244/344/270/216/346/235/216/344/273/243/346/225/260/01_SE2/345/205/254/345/274/217/346/216/250/345/257/274(sympy).py +41 -0
  29. akai_transform-0.0.1/example//347/251/272/351/227/264/345/217/230/346/215/242/345/237/272/347/241/200/346/241/210/344/276/213(akai_transform)/04./346/235/216/347/276/244/344/270/216/346/235/216/344/273/243/346/225/260/01_SE2/346/214/207/346/225/260/346/230/240/345/260/204/344/270/216/345/257/271/346/225/260/346/230/240/345/260/204.py +270 -0
  30. akai_transform-0.0.1/example//347/251/272/351/227/264/345/217/230/346/215/242/345/237/272/347/241/200/346/241/210/344/276/213(akai_transform)/04./346/235/216/347/276/244/344/270/216/346/235/216/344/273/243/346/225/260/02_SE3/346/214/207/346/225/260/346/230/240/345/260/204/344/270/216/345/257/271/346/225/260/346/230/240/345/260/204.py +339 -0
  31. akai_transform-0.0.1/example//347/251/272/351/227/264/345/217/230/346/215/242/345/237/272/347/241/200/346/241/210/344/276/213(akai_transform)/04./346/235/216/347/276/244/344/270/216/346/235/216/344/273/243/346/225/260//345/205/266/344/273/226/345/267/245/345/205/267/350/204/232/346/234/254/se2_visual_cross_product.py +88 -0
  32. akai_transform-0.0.1/example//347/251/272/351/227/264/345/217/230/346/215/242/345/237/272/347/241/200/346/241/210/344/276/213(akai_transform)/04./346/235/216/347/276/244/344/270/216/346/235/216/344/273/243/346/225/260//345/205/266/344/273/226/345/267/245/345/205/267/350/204/232/346/234/254/visual_one_minus_cosw_over_w.py +269 -0
  33. akai_transform-0.0.1/example//347/251/272/351/227/264/345/217/230/346/215/242/345/237/272/347/241/200/346/241/210/344/276/213(akai_transform)/04./346/235/216/347/276/244/344/270/216/346/235/216/344/273/243/346/225/260//345/205/266/344/273/226/345/267/245/345/205/267/350/204/232/346/234/254/visual_se2.py +327 -0
  34. akai_transform-0.0.1/example//347/251/272/351/227/264/345/217/230/346/215/242/345/237/272/347/241/200/346/241/210/344/276/213(akai_transform)/04./346/235/216/347/276/244/344/270/216/346/235/216/344/273/243/346/225/260//345/205/266/344/273/226/345/267/245/345/205/267/350/204/232/346/234/254/visual_sinw_div_w.py +73 -0
  35. akai_transform-0.0.1/example//347/251/272/351/227/264/345/217/230/346/215/242/345/237/272/347/241/200/346/241/210/344/276/213(akai_transform)/04./346/235/216/347/276/244/344/270/216/346/235/216/344/273/243/346/225/260//345/205/266/344/273/226/345/267/245/345/205/267/350/204/232/346/234/254/visual_sinw_geometric_meaning.py +269 -0
  36. akai_transform-0.0.1/example//347/251/272/351/227/264/345/217/230/346/215/242/345/237/272/347/241/200/346/241/210/344/276/213(akai_transform)/04./346/235/216/347/276/244/344/270/216/346/235/216/344/273/243/346/225/260//345/205/266/344/273/226/345/267/245/345/205/267/350/204/232/346/234/254/visual_sinw_over_w_meaning.py +247 -0
  37. akai_transform-0.0.1/example//347/251/272/351/227/264/345/217/230/346/215/242/345/237/272/347/241/200/346/241/210/344/276/213(akai_transform)/04./346/235/216/347/276/244/344/270/216/346/235/216/344/273/243/346/225/260//345/205/266/344/273/226/345/267/245/345/205/267/350/204/232/346/234/254/visual_t_v_angle_relation.py +330 -0
  38. akai_transform-0.0.1/example//347/251/272/351/227/264/345/217/230/346/215/242/345/237/272/347/241/200/346/241/210/344/276/213(akai_transform)/04./346/235/216/347/276/244/344/270/216/346/235/216/344/273/243/346/225/260//345/205/266/344/273/226/345/267/245/345/205/267/350/204/232/346/234/254/visual_trigonometric_function.py +73 -0
  39. akai_transform-0.0.1/image/akai_3d_big.jpg +0 -0
  40. akai_transform-0.0.1/image/akai_wechat_qrcode.png +0 -0
  41. akai_transform-0.0.1/image//346/226/207/346/241/243/346/210/252/345/233/276.png +0 -0
  42. akai_transform-0.0.1/image//351/230/277/345/207/257/347/251/272/351/227/264/345/217/230/346/215/242/345/272/223ICON-V2.png +0 -0
  43. akai_transform-0.0.1/pyproject.toml +46 -0
  44. akai_transform-0.0.1/setup.cfg +4 -0
@@ -0,0 +1,301 @@
1
+ # akai_transform 编程指南
2
+
3
+ 纯 Python 空间变换工具库,提供 2D/3D 空间变换、四元数运算、SE(3) 李群/李代数、对数四元数等功能。仅依赖 `numpy`。
4
+
5
+ ---
6
+
7
+ ## 模块总览
8
+
9
+ | 模块 | 导入方式 | 功能 |
10
+ |---|---|---|
11
+ | `tf2d` | `from akai_transform import tf2d` | 2D 空间变换(3×3 齐次矩阵) |
12
+ | `tf3d` | `from akai_transform import tf3d` | 3D 空间变换(4×4 齐次矩阵) |
13
+ | `quat` | `from akai_transform import quat` | 四元数运算 |
14
+ | `se3` | `from akai_transform import se3` | SE(3) 李群/李代数 |
15
+ | `log_quat` | `from akai_transform import log_quat` | 对数四元数 |
16
+ | `const` | `from akai_transform import const` | 常量和枚举 |
17
+
18
+ ### 常量便捷导入
19
+
20
+ ```python
21
+ from akai_transform import MM, M, DEG, RAD, PI, DEG2RAD, RAD2DEG
22
+ ```
23
+
24
+ ---
25
+
26
+ ## 约定
27
+
28
+ - **欧拉角**:ZYX 内旋(RPY),`[roll, pitch, yaw]` = `[绕X, 绕Y, 绕Z]`
29
+ - **角度单位**:默认弧度(rad),需要度时通过参数 `rpy_unit=DEG` 指定
30
+ - **四元数**:`[w, x, y, z]` 标量在前
31
+ - **2D 变换矩阵**:3×3 齐次矩阵
32
+ - **3D 变换矩阵**:4×4 齐次矩阵
33
+ - **平移单位**:通过 `MM`(毫米)或 `M`(米)枚举指定
34
+
35
+ ---
36
+
37
+ ## tf2d — 2D 空间变换
38
+
39
+ ```python
40
+ from akai_transform import tf2d
41
+
42
+ # 创建矩阵
43
+ R = tf2d.rmat(np.pi / 4) # 旋转 45°
44
+ D = tf2d.dmat(100, 200) # 平移 (100, 200)
45
+ Dx = tf2d.dx(50) # 仅沿 X 轴平移
46
+ Dy = tf2d.dy(30) # 仅沿 Y 轴平移
47
+ T = tf2d.tmat(100, 200, np.pi / 4) # 旋转 + 平移
48
+
49
+ # 操作
50
+ T_inv = tf2d.inv(T) # 利用正交性加速求逆
51
+ v_a = tf2d.vec_transform(T, [10, 20]) # 坐标变换
52
+ theta = tf2d.rmat2theta(R) # 提取角度
53
+
54
+ # 由两向量求旋转
55
+ theta = tf2d.theta_between_vecs([1,0], [0,1]) # 求旋转角度
56
+ R = tf2d.rmat_between_vecs([1,0], [0,1]) # 求旋转矩阵
57
+
58
+ # 近似相等判断
59
+ tf2d.approx_equal_mat(T @ tf2d.inv(T), np.eye(3)) # True
60
+ tf2d.approx_equal_vec([1.0, 2.0], [1.0, 2.0]) # True
61
+ ```
62
+
63
+ ---
64
+
65
+ ## tf3d — 3D 空间变换
66
+
67
+ ### 创建矩阵
68
+
69
+ ```python
70
+ from akai_transform import tf3d
71
+
72
+ R = tf3d.rmat(roll=0.1, pitch=0.2, yaw=0.3) # ZYX 内旋
73
+ Rx = tf3d.rx(0.1); Ry = tf3d.ry(0.2); Rz = tf3d.rz(0.3)
74
+ D = tf3d.dmat(100, 200, 300)
75
+ Dx = tf3d.dx(100); Dy = tf3d.dy(200); Dz = tf3d.dz(300) # 单轴平移
76
+ T = tf3d.tmat(100, 200, 300, 0.1, 0.2, 0.3)
77
+ ```
78
+
79
+ ### 变换操作
80
+
81
+ ```python
82
+ T_inv = tf3d.inv(T) # 利用正交性加速求逆
83
+ v_a = tf3d.vec_transform(T, [10, 20, 30]) # 坐标变换
84
+ T_mm = tf3d.tmat_m2mm(T) # 米 → 毫米
85
+ T_m = tf3d.tmat_mm2m(T_mm) # 毫米 → 米
86
+ ```
87
+
88
+ ### 旋转表示转换
89
+
90
+ ```python
91
+ # 欧拉角 ↔ 旋转矩阵
92
+ R = tf3d.euler2rmat(euler)
93
+ euler = tf3d.rmat2euler(R)
94
+
95
+ # 旋转向量 ↔ 旋转矩阵
96
+ R = tf3d.rvec2rmat(n, theta)
97
+ n, theta = tf3d.rmat2rvec(R)
98
+
99
+ # 四元数 ↔ 旋转矩阵/欧拉角/旋转向量
100
+ q = tf3d.rmat2quat(R); R = tf3d.quat2rmat(q)
101
+ q = tf3d.euler2quat(euler); euler = tf3d.quat2euler(q)
102
+ q = tf3d.rvec2quat(n, theta); n, theta = tf3d.quat2rvec(q)
103
+
104
+ # 修正罗德里格斯参数(MRP)
105
+ mrp = tf3d.rmat2mrp(R); R = tf3d.mrp2rmat(mrp)
106
+ ```
107
+
108
+ ### 由两向量求旋转
109
+
110
+ ```python
111
+ v = [1, 0, 0]; v_dot = [0, 1, 0]
112
+ n, theta = tf3d.rvec_between_vecs(v, v_dot) # 旋转向量
113
+ R = tf3d.rmat_between_vecs(v, v_dot) # 旋转矩阵
114
+ ```
115
+
116
+ ### XYZRPY 便捷接口(机械臂常用)
117
+
118
+ ```python
119
+ from akai_transform import tf3d, MM, M, DEG, RAD
120
+
121
+ # 机械臂位姿 → 变换矩阵
122
+ xyzrpy = [400, 0, 300, 180, 0, 0] # mm + deg
123
+ T = tf3d.xyzrpy2tmat(xyzrpy, xyz_unit=MM, rpy_unit=DEG, t_unit=MM)
124
+
125
+ # 变换矩阵 → 机械臂位姿
126
+ xyzrpy = tf3d.tmat2xyzrpy(T, t_unit=MM, xyz_unit=MM, rpy_unit=DEG)
127
+
128
+ # 姿态增量变换(右乘增量)
129
+ new_xyzrpy = tf3d.xyzrpy_transform(xyzrpy, x=10, y=0, z=0,
130
+ roll=0, pitch=0, yaw=5, rpy_unit=DEG)
131
+
132
+ # XYZRPY 求逆
133
+ inv_xyzrpy = tf3d.xyzrpy_inv(xyzrpy, rpy_unit=DEG)
134
+ ```
135
+
136
+ ### 高层工具
137
+
138
+ ```python
139
+ T_mean = tf3d.tmat_mean([T1, T2, T3]) # 多个变换矩阵求均值
140
+ R_clean = tf3d.orthogonalize_rmat(noisy_R) # SVD 正交化
141
+ dist, theta = tf3d.pose_error(T_real, T_est, is_debug=True)
142
+ # 输出: 平移误差(mm) + 角度误差(deg)
143
+ ```
144
+
145
+ ---
146
+
147
+ ## quat — 四元数运算
148
+
149
+ 四元数格式统一为 `[w, x, y, z]`(标量在前)。
150
+
151
+ ```python
152
+ from akai_transform import quat
153
+
154
+ # 基础操作
155
+ q_id = quat.identity() # [1, 0, 0, 0]
156
+ n = quat.norm(q) # 模长
157
+ ok = quat.is_unit(q) # 是否为单位四元数
158
+ q_n = quat.normalize(q) # 归一化
159
+ q_conj = quat.conjugate(q) # 共轭 [w, -x, -y, -z]
160
+ q_neg = quat.reverse(q) # 取反 [-w, -x, -y, -z]
161
+ q_inv = quat.inv(q) # 求逆
162
+
163
+ # 运算
164
+ d = quat.dot(q1, q2) # 点乘
165
+ q_prod = quat.multiply(q1, q2) # Hamilton 积
166
+
167
+ # 向量旋转
168
+ v_rot = quat.rotate_vec(q, [1, 0, 0]) # 单个四元数旋转单个向量
169
+ v_list = quat.rotate_vec_nq(q_list, [1, 0, 0]) # 多个四元数旋转同一向量
170
+ v_list = quat.rotate_vec_nv(q, v_list) # 同一四元数旋转多个向量
171
+
172
+ # 度量
173
+ theta, is_reversed = quat.angle_diff(q1, q2, select_min=True)
174
+ q_delta = quat.relative_rotation(q1, q2) # q_delta * q1 = q2
175
+
176
+ # 插值
177
+ q_lerp = quat.lerp(q1, q2, 0.5) # 线性插值(结果非单位四元数)
178
+ q_nlerp = quat.nlerp(q1, q2, 0.5) # 正规化线性插值
179
+ q_slerp = quat.slerp(q1, q2, 0.5) # 球面线性插值(推荐)
180
+ q_list = quat.interp_p2p(q1, q2, t_list, short_path=True) # 批量插值
181
+
182
+ # Squad 插值(多途径点平滑插值)
183
+ q_interp = quat.squad(q0, q1, s0, s1, t) # 单次 Squad 插值
184
+ s = quat.compute_control_quat(q_prev, q_curr, q_next) # 计算控制四元数
185
+
186
+ # 多途径点插值(自动处理控制点)
187
+ q_list_slerp = quat.interp_multi_waypoints(q_waypoints, t_list, method='slerp') # 分段线性
188
+ q_list_squad = quat.interp_multi_waypoints(q_waypoints, t_list, method='squad') # 平滑过渡
189
+
190
+ # 统计
191
+ q_mean = quat.mean([q1, q2, q3, q4]) # 最大特征值法
192
+ ```
193
+
194
+ ---
195
+
196
+ ## se3 — SE(3) 李群/李代数
197
+
198
+ ```python
199
+ from akai_transform import se3
200
+
201
+ # hat/vee 算子
202
+ omega_hat = se3.hat([1, 2, 3]) # R³ → so(3)
203
+ omega = se3.vee(omega_hat) # so(3) → R³
204
+
205
+ # SO(3) 指数/对数映射
206
+ R = se3.exp_so3([0.1, 0.2, 0.3])
207
+ omega = se3.log_so3(R)
208
+
209
+ # SE(3) 指数/对数映射
210
+ T = se3.exp_se3(omega, v)
211
+ omega, v = se3.log_se3(T)
212
+
213
+ # 6维李代数 ↔ 变换矩阵
214
+ xi = np.array([1, 2, 3, 0.1, 0.2, 0.3]) # [vx,vy,vz,wx,wy,wz]
215
+ T = se3.xi2tmat(xi)
216
+ xi = se3.tmat2xi(T)
217
+
218
+ # SE(3) 螺旋插值
219
+ T_mid = se3.interp_se3(T_start, T_end, t=0.5)
220
+ ```
221
+
222
+ ---
223
+
224
+ ## log_quat — 对数四元数
225
+
226
+ ```python
227
+ from akai_transform import log_quat
228
+
229
+ # 四元数 ↔ 对数空间
230
+ v = log_quat.quat2log(q) # 单位四元数 → R³
231
+ q = log_quat.log2quat(v) # R³ → 单位四元数
232
+
233
+ # 支持批量处理 (N,4) → (N,3)
234
+ v_batch = log_quat.quat2log(q_batch)
235
+ q_batch = log_quat.log2quat(v_batch)
236
+ ```
237
+
238
+ ---
239
+
240
+ ## 常用代码模板
241
+
242
+ ### 机械臂位姿处理
243
+
244
+ ```python
245
+ from akai_transform import tf3d, MM, DEG
246
+
247
+ # 法奥机械臂 XYZRPY → 变换矩阵
248
+ T = tf3d.xyzrpy2tmat([400, 0, 300, 180, 0, 0], xyz_unit=MM, rpy_unit=DEG, t_unit=MM)
249
+
250
+ # 工具偏移
251
+ T_tool = T @ tf3d.tmat(0, 0, 50, 0, 0, 0)
252
+
253
+ # 逆变换
254
+ T_inv = tf3d.inv(T_tool)
255
+ ```
256
+
257
+ ### 坐标系链式变换
258
+
259
+ ```python
260
+ T_a2c = T_a2b @ T_b2c # A→B→C
261
+ T_a2b = T_a2c @ tf3d.inv(T_b2c) # 已知 A→C 和 B→C,求 A→B
262
+ ```
263
+
264
+ ### 姿态插值
265
+
266
+ ```python
267
+ from akai_transform import tf3d, quat, se3
268
+
269
+ # 四元数 Slerp 插值(两点间)
270
+ q1 = tf3d.euler2quat([0, 0, 0])
271
+ q2 = tf3d.euler2quat([0, 0, np.pi / 2])
272
+ q_list = quat.interp_p2p(q1, q2, np.linspace(0, 1, 50))
273
+
274
+ # 多途径点姿态插值
275
+ q_waypoints = [tf3d.euler2quat(rpy) for rpy in rpy_list]
276
+ t_interp = np.linspace(0, len(q_waypoints) - 1, 500)
277
+
278
+ # 方法 1: Slerp(分段线性,类似位置空间的折线)
279
+ q_list_slerp = quat.interp_multi_waypoints(q_waypoints, t_interp, method='slerp')
280
+
281
+ # 方法 2: Squad(平滑过渡,类似位置空间的圆弧过渡)
282
+ q_list_squad = quat.interp_multi_waypoints(q_waypoints, t_interp, method='squad')
283
+
284
+ # SE(3) 螺旋插值(同时插值位置和姿态)
285
+ T_list = [se3.interp_se3(T_start, T_end, t) for t in np.linspace(0, 1, 50)]
286
+ ```
287
+
288
+ **Slerp vs Squad 对比**:
289
+
290
+ | 特性 | Slerp | Squad |
291
+ |------|-------|-------|
292
+ | 连续性 | C0(位置连续) | C1(速度连续) |
293
+ | 角速度 | 途径点处有突变 | 平滑连续 |
294
+ | 类比 | 位置空间的折线 | 位置空间的圆弧过渡 |
295
+ | 适用场景 | 简单路径、快速计算 | 高质量轨迹、减少机械冲击 |
296
+ | 计算复杂度 | 低 | 中等 |
297
+
298
+ **使用建议**:
299
+ - 机械臂轨迹规划:优先使用 Squad,减少机械应力
300
+ - 实时控制:Slerp 计算更快
301
+ - 可视化动画:Squad 更平滑自然
@@ -0,0 +1,5 @@
1
+ include README.md
2
+ include CLAUDE.md
3
+ recursive-include akai_transform *.py
4
+ recursive-include example *.py
5
+ recursive-include image *
@@ -0,0 +1,127 @@
1
+ Metadata-Version: 2.4
2
+ Name: akai-transform
3
+ Version: 0.0.1
4
+ Summary: AKAI Spatial Transform Library
5
+ Author-email: Shunkai Xing <xingshunkai@qq.com>
6
+ Project-URL: Homepage, https://anyi.deepsenserobot.com/
7
+ Keywords: spatial-transform,robotics,quaternion,euler-angles,se3,so3
8
+ Classifier: Development Status :: 4 - Beta
9
+ Classifier: Programming Language :: Python :: 3
10
+ Classifier: Programming Language :: Python :: 3.8
11
+ Classifier: Programming Language :: Python :: 3.9
12
+ Classifier: Programming Language :: Python :: 3.10
13
+ Classifier: Programming Language :: Python :: 3.11
14
+ Classifier: Programming Language :: Python :: 3.12
15
+ Classifier: Programming Language :: Python :: 3.13
16
+ Classifier: Programming Language :: Python :: 3.14
17
+ Classifier: Programming Language :: Python :: 3.15
18
+ Classifier: Operating System :: OS Independent
19
+ Classifier: Intended Audience :: Science/Research
20
+ Classifier: Intended Audience :: Developers
21
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
22
+ Classifier: Topic :: Scientific/Engineering
23
+ Requires-Python: >=3.8
24
+ Description-Content-Type: text/markdown
25
+ Requires-Dist: numpy
26
+ Provides-Extra: examples
27
+
28
+ # 阿凯空间变换库(akai-transform)
29
+
30
+ 纯 Python 空间变换工具库,提供 2D/3D 空间变换、四元数运算、SE(3) 李群/李代数、对数四元数等功能。仅依赖 `numpy`。
31
+
32
+ ![](./image/阿凯空间变换库ICON-V2.png)
33
+
34
+ ## 文档
35
+
36
+ - [阿凯爱玩机器人 课程官网](https://anyi.deepsenserobot.com/)
37
+ - [理论基础-空间变换基础入门](https://anyi.deepsenserobot.com/course/akai-transform-course)
38
+ - [阿凯空间变换库(akai-transform)使用手册](https://anyi.deepsenserobot.com/course/akai-transform-manual)
39
+
40
+ ![](./image/文档截图.png)
41
+
42
+
43
+
44
+ ## 安装
45
+
46
+ ```bash
47
+ pip install akai-transform
48
+ ```
49
+
50
+
51
+
52
+ ## 模块总览
53
+
54
+ | 模块 | 导入方式 | 功能 |
55
+ |---|---|---|
56
+ | `tf2d` | `from akai_transform import tf2d` | 2D 空间变换(3×3 齐次矩阵) |
57
+ | `tf3d` | `from akai_transform import tf3d` | 3D 空间变换(4×4 齐次矩阵) |
58
+ | `quat` | `from akai_transform import quat` | 四元数运算 |
59
+ | `se3` | `from akai_transform import se3` | SE(3) 李群/李代数 |
60
+ | `log_quat` | `from akai_transform import log_quat` | 对数四元数 |
61
+ | `const` | `from akai_transform import const` | 常量和枚举 |
62
+
63
+
64
+
65
+ ## 约定
66
+
67
+ - **欧拉角**:ZYX 内旋(RPY),`[roll, pitch, yaw]` = `[绕X, 绕Y, 绕Z]`
68
+ - **角度单位**:默认弧度(rad),需要度时通过参数 `rpy_unit=DEG` 指定
69
+ - **四元数**:`[w, x, y, z]` 标量在前
70
+ - **2D 变换矩阵**:3×3 齐次矩阵
71
+ - **3D 变换矩阵**:4×4 齐次矩阵
72
+ - **平移单位**:通过 `MM`(毫米)或 `M`(米)枚举指定
73
+
74
+
75
+
76
+ ## 案例列表
77
+
78
+ 完整案例代码位于 `example/空间变换基础案例(akai_transform)/` 目录下。
79
+
80
+ ### 2D空间变换
81
+
82
+ | 文件 | 说明 |
83
+ |---|---|
84
+ | `01_tf2d_基础测试.py` | tf2d 基础测试 |
85
+ | `02_tf2d_小乌龟可视化.py` | 小乌龟可视化 |
86
+
87
+ ### 3D空间变换(基础)
88
+
89
+ | 文件 | 说明 |
90
+ |---|---|
91
+ | `01_tf3d_旋转矩阵与平移矩阵.py` | 旋转矩阵与平移矩阵 |
92
+ | `02_tf3d_旋转向量.py` | 旋转向量 |
93
+ | `03_tf3d_四元数转换.py` | 四元数转换 |
94
+ | `04_tf3d_XYZRPY.py` | XYZRPY 便捷接口 |
95
+ | `05_tf3d_Open3D可视化.py` | Open3D 可视化 |
96
+
97
+ ### 3D空间变换(进阶)
98
+
99
+ | 文件 | 说明 |
100
+ |---|---|
101
+ | `01_修正罗德里格斯参数(MRP).py` | 修正罗德里格斯参数 |
102
+ | `02_四元数基础运算.py` | 四元数基础运算 |
103
+ | `03_对数四元数转换.py` | 对数四元数转换 |
104
+ | `04_多途径点位置姿态插值_Slerp_vs_Squad.py` | Slerp vs Squad 插值对比 |
105
+
106
+ ### 李群与李代数
107
+
108
+ | 文件 | 说明 |
109
+ |---|---|
110
+ | `01_SE2公式推导(sympy).py` | SE2 公式推导(SymPy) |
111
+ | `01_SE2指数映射与对数映射.py` | SE2 指数/对数映射 |
112
+ | `02_SE3指数映射与对数映射.py` | SE3 指数/对数映射 |
113
+ | `其他工具脚本/` | 三角函数可视化等辅助脚本 |
114
+
115
+ ## 作者
116
+
117
+ **阿凯爱玩机器人**
118
+
119
+ <img src="image/akai_3d_big.jpg" width="200" />
120
+
121
+ 扫码添加微信,一起交流机器人技术:
122
+
123
+ <img src="image/akai_wechat_qrcode.png" width="200" />
124
+
125
+ ## 许可证
126
+
127
+ MIT License
@@ -0,0 +1,100 @@
1
+ # 阿凯空间变换库(akai-transform)
2
+
3
+ 纯 Python 空间变换工具库,提供 2D/3D 空间变换、四元数运算、SE(3) 李群/李代数、对数四元数等功能。仅依赖 `numpy`。
4
+
5
+ ![](./image/阿凯空间变换库ICON-V2.png)
6
+
7
+ ## 文档
8
+
9
+ - [阿凯爱玩机器人 课程官网](https://anyi.deepsenserobot.com/)
10
+ - [理论基础-空间变换基础入门](https://anyi.deepsenserobot.com/course/akai-transform-course)
11
+ - [阿凯空间变换库(akai-transform)使用手册](https://anyi.deepsenserobot.com/course/akai-transform-manual)
12
+
13
+ ![](./image/文档截图.png)
14
+
15
+
16
+
17
+ ## 安装
18
+
19
+ ```bash
20
+ pip install akai-transform
21
+ ```
22
+
23
+
24
+
25
+ ## 模块总览
26
+
27
+ | 模块 | 导入方式 | 功能 |
28
+ |---|---|---|
29
+ | `tf2d` | `from akai_transform import tf2d` | 2D 空间变换(3×3 齐次矩阵) |
30
+ | `tf3d` | `from akai_transform import tf3d` | 3D 空间变换(4×4 齐次矩阵) |
31
+ | `quat` | `from akai_transform import quat` | 四元数运算 |
32
+ | `se3` | `from akai_transform import se3` | SE(3) 李群/李代数 |
33
+ | `log_quat` | `from akai_transform import log_quat` | 对数四元数 |
34
+ | `const` | `from akai_transform import const` | 常量和枚举 |
35
+
36
+
37
+
38
+ ## 约定
39
+
40
+ - **欧拉角**:ZYX 内旋(RPY),`[roll, pitch, yaw]` = `[绕X, 绕Y, 绕Z]`
41
+ - **角度单位**:默认弧度(rad),需要度时通过参数 `rpy_unit=DEG` 指定
42
+ - **四元数**:`[w, x, y, z]` 标量在前
43
+ - **2D 变换矩阵**:3×3 齐次矩阵
44
+ - **3D 变换矩阵**:4×4 齐次矩阵
45
+ - **平移单位**:通过 `MM`(毫米)或 `M`(米)枚举指定
46
+
47
+
48
+
49
+ ## 案例列表
50
+
51
+ 完整案例代码位于 `example/空间变换基础案例(akai_transform)/` 目录下。
52
+
53
+ ### 2D空间变换
54
+
55
+ | 文件 | 说明 |
56
+ |---|---|
57
+ | `01_tf2d_基础测试.py` | tf2d 基础测试 |
58
+ | `02_tf2d_小乌龟可视化.py` | 小乌龟可视化 |
59
+
60
+ ### 3D空间变换(基础)
61
+
62
+ | 文件 | 说明 |
63
+ |---|---|
64
+ | `01_tf3d_旋转矩阵与平移矩阵.py` | 旋转矩阵与平移矩阵 |
65
+ | `02_tf3d_旋转向量.py` | 旋转向量 |
66
+ | `03_tf3d_四元数转换.py` | 四元数转换 |
67
+ | `04_tf3d_XYZRPY.py` | XYZRPY 便捷接口 |
68
+ | `05_tf3d_Open3D可视化.py` | Open3D 可视化 |
69
+
70
+ ### 3D空间变换(进阶)
71
+
72
+ | 文件 | 说明 |
73
+ |---|---|
74
+ | `01_修正罗德里格斯参数(MRP).py` | 修正罗德里格斯参数 |
75
+ | `02_四元数基础运算.py` | 四元数基础运算 |
76
+ | `03_对数四元数转换.py` | 对数四元数转换 |
77
+ | `04_多途径点位置姿态插值_Slerp_vs_Squad.py` | Slerp vs Squad 插值对比 |
78
+
79
+ ### 李群与李代数
80
+
81
+ | 文件 | 说明 |
82
+ |---|---|
83
+ | `01_SE2公式推导(sympy).py` | SE2 公式推导(SymPy) |
84
+ | `01_SE2指数映射与对数映射.py` | SE2 指数/对数映射 |
85
+ | `02_SE3指数映射与对数映射.py` | SE3 指数/对数映射 |
86
+ | `其他工具脚本/` | 三角函数可视化等辅助脚本 |
87
+
88
+ ## 作者
89
+
90
+ **阿凯爱玩机器人**
91
+
92
+ <img src="image/akai_3d_big.jpg" width="200" />
93
+
94
+ 扫码添加微信,一起交流机器人技术:
95
+
96
+ <img src="image/akai_wechat_qrcode.png" width="200" />
97
+
98
+ ## 许可证
99
+
100
+ MIT License
@@ -0,0 +1,31 @@
1
+ '''
2
+ akai_transform — 空间变换工具库
3
+ ----------------------------------------------------------------
4
+ 提供 2D/3D 空间变换、四元数运算、SE(3) 李群/李代数、对数四元数等功能。
5
+
6
+ 子模块:
7
+ - tf2d: 2D 空间变换(3×3 齐次变换矩阵)
8
+ - tf3d: 3D 空间变换(4×4 齐次变换矩阵)
9
+ - quat: 四元数运算([w, x, y, z] 标量在前)
10
+ - se3: SE(3) 李群/李代数(指数/对数映射)
11
+ - log_quat: 对数四元数(四元数 ↔ R³ 旋转向量)
12
+ - const: 常量和枚举定义
13
+
14
+ 作者: 阿凯爱玩机器人 | 微信: xingshunkai | QQ: 244561792
15
+ 官网: deepsenserobot.com
16
+ B站: https://space.bilibili.com/40344504
17
+ '''
18
+
19
+ from . import const
20
+ from . import tf2d
21
+ from . import tf3d
22
+ from . import quat
23
+ from . import se3
24
+ from . import log_quat
25
+
26
+ # 常量便捷导出
27
+ from .const import (
28
+ PI, DEG2RAD, RAD2DEG, PI_2, PI_D_2,
29
+ TranslationUnit, AngleUnit,
30
+ MM, M, DEG, RAD,
31
+ )
@@ -0,0 +1,51 @@
1
+ '''
2
+ 常量与枚举定义
3
+ ----------------------------------------------------------------
4
+ 提供空间变换库所需的数学常量和单位枚举。
5
+
6
+ 作者: 阿凯爱玩机器人 | 微信: xingshunkai | QQ: 244561792
7
+ 官网: deepsenserobot.com
8
+ B站: https://space.bilibili.com/40344504
9
+ '''
10
+
11
+ import math
12
+ from enum import IntEnum
13
+
14
+ # ============================================================
15
+ # 数学常量
16
+ # ============================================================
17
+
18
+ PI = math.pi
19
+ '''圆周率'''
20
+
21
+ DEG2RAD = math.pi / 180.0
22
+ '''角度转弧度系数'''
23
+
24
+ RAD2DEG = 180.0 / math.pi
25
+ '''弧度转角度系数'''
26
+
27
+ PI_2 = math.pi * 2.0
28
+ '''两倍圆周率 (2π)'''
29
+
30
+ PI_D_2 = math.pi / 2.0
31
+ '''圆周率的一半 (π/2)'''
32
+
33
+ # ============================================================
34
+ # 单位枚举
35
+ # ============================================================
36
+
37
+ class TranslationUnit(IntEnum):
38
+ '''平移量单位枚举'''
39
+ MM = 0 # 毫米
40
+ M = 1 # 米
41
+
42
+ class AngleUnit(IntEnum):
43
+ '''角度单位枚举'''
44
+ DEG = 0 # 度
45
+ RAD = 1 # 弧度
46
+
47
+ # 便捷别名
48
+ MM = TranslationUnit.MM
49
+ M = TranslationUnit.M
50
+ DEG = AngleUnit.DEG
51
+ RAD = AngleUnit.RAD
@@ -0,0 +1,84 @@
1
+ '''
2
+ 对数四元数模块
3
+ ----------------------------------------------------------------
4
+ 提供四元数与对数四元数(R³ 旋转向量)之间的映射,
5
+ 用于姿态插值和优化。
6
+
7
+ 理论基础:
8
+ - 对数映射: SO(3) → so(3), q → log(q)
9
+ - 指数映射: so(3) → SO(3), v → exp(v)
10
+ - 应用场景: 姿态插值、轨迹规划、姿态优化等
11
+
12
+ 作者: 阿凯爱玩机器人 | 微信: xingshunkai | QQ: 244561792
13
+ 官网: deepsenserobot.com
14
+ B站: https://space.bilibili.com/40344504
15
+ '''
16
+
17
+ import numpy as np
18
+
19
+
20
+ def quat2log(q):
21
+ '''单位四元数 → 对数四元数(R³ 旋转向量)
22
+
23
+ 使用对数映射将 SO(3) 群映射到其李代数 so(3) ≅ R³。
24
+ 支持单个或批量四元数输入。
25
+
26
+ :param q: 单位四元数 [w, x, y, z],形状为 (4,) 或 (..., 4)
27
+ :return: 对数四元数(旋转向量) [vx, vy, vz],形状为 (3,) 或 (..., 3)
28
+ '''
29
+ q = np.asarray(q, dtype=np.float64)
30
+ original_shape = q.shape
31
+
32
+ if q.ndim == 1:
33
+ q = q.reshape(1, -1)
34
+
35
+ # 归一化
36
+ q = q / np.linalg.norm(q, axis=-1, keepdims=True)
37
+
38
+ w = q[..., 0]
39
+ vec = q[..., 1:]
40
+ norm_vec = np.linalg.norm(vec, axis=-1)
41
+
42
+ log_q = np.zeros((*q.shape[:-1], 3), dtype=np.float64)
43
+
44
+ mask = norm_vec >= 1e-6
45
+ if np.any(mask):
46
+ theta = 2.0 * np.arctan2(norm_vec[mask], w[mask])
47
+ axis = vec[mask] / norm_vec[mask, np.newaxis]
48
+ log_q[mask] = axis * theta[:, np.newaxis]
49
+
50
+ if len(original_shape) == 1:
51
+ return log_q[0]
52
+ return log_q
53
+
54
+
55
+ def log2quat(v):
56
+ '''对数四元数(R³ 旋转向量) → 单位四元数
57
+
58
+ 使用指数映射将李代数 so(3) 映射回 SO(3) 群。
59
+ 支持单个或批量输入。
60
+
61
+ :param v: 对数四元数(旋转向量) [vx, vy, vz],形状为 (3,) 或 (..., 3)
62
+ :return: 单位四元数 [w, x, y, z],形状为 (4,) 或 (..., 4)
63
+ '''
64
+ v = np.asarray(v, dtype=np.float64)
65
+ original_shape = v.shape
66
+
67
+ if v.ndim == 1:
68
+ v = v.reshape(1, -1)
69
+
70
+ theta = np.linalg.norm(v, axis=-1)
71
+
72
+ q = np.zeros((*v.shape[:-1], 4), dtype=np.float64)
73
+ q[..., 0] = 1.0
74
+
75
+ mask = theta >= 1e-6
76
+ if np.any(mask):
77
+ axis = v[mask] / theta[mask, np.newaxis]
78
+ half_theta = 0.5 * theta[mask]
79
+ q[mask, 0] = np.cos(half_theta)
80
+ q[mask, 1:] = axis * np.sin(half_theta)[:, np.newaxis]
81
+
82
+ if len(original_shape) == 1:
83
+ return q[0]
84
+ return q