• myCobot pro 机械臂(6)逆向运动学


    机械臂逆运动学求解常用的方法有几何法、解析法、数值法

    从求解的方式和计算的效率上来看,几何法和解析法会考虑机械臂结构不同而造成的差异,因此对于不同结构的机械臂会有特定的求解方式。

    通常来说,这两种方法具有速度快、精度高的优点和通用性差、普适性低的缺点。而数值法则通常有相对统一的求解方式,具有适用性好但速度慢、数值稳定性差的特点。

    对于工业机器人而言,通常处于特定的工作环境中,为了满足一定的工作性能要求而常采用解析法进行求解。

    本文将使用解析法对该型机械臂进行逆运动学的求解。

     

    下面通过Python代码的形式将这些推导的公式表示出来:

    1. # 输入位姿矩阵T
    2. # 例如:T=np.matrix(np.array([[0.5,-0.7,-0.3,36],[-0.3,-0.6,0.6,-28.3],[-0.7,-0.2,-0.6,355.7],[0,0,0,1]]))
    3. # 输出解的列表q_list,里面的一个列表就代表一组解
    4. # 例如:q_list=[[q1_1,q21,……],[],[],……]
    5. def ikine_6DOF(T):
    6. # 提取元素
    7. nx = T[0, 0]
    8. ny = T[1, 0]
    9. nz = T[2, 0]
    10. ox = T[0, 1]
    11. oy = T[1, 1]
    12. oz = T[2, 1]
    13. ax = T[0, 2]
    14. ay = T[1, 2]
    15. az = T[2, 2]
    16. px = T[0, 3]
    17. py = T[1, 3]
    18. pz = T[2, 3]
    19. # 求解q1
    20. # 见论文公式(2.23)
    21. q1_1 = 2 * np.arctan2(px - ax * d6 + np.sqrt((px - ax * d6) ** 2 + (-py + ay * d6) ** 2 - d4 ** 2),
    22. d4 - py + ay * d6)
    23. print(q1_1)
    24. if q1_1 < q1_range[0] or q1_1 > q1_range[1]:
    25. q1_1 = False
    26. q1_2 = 2 * np.arctan2(px - ax * d6 - np.sqrt((px - ax * d6) ** 2 + (-py + ay * d6) ** 2 - d4 ** 2),
    27. d4 - py + ay * d6)
    28. if q1_2 < q1_range[0] or q1_2 > q1_range[1]:
    29. q1_2 = False
    30. # 求解q6
    31. # 见论文公式(2.29)
    32. q6_1 = np.arctan2(ox * np.sin(q1_1) - oy * np.cos(q1_1), ny * np.cos(q1_1) - nx * np.sin(q1_1)) + np.pi
    33. q6_2 = np.arctan2(ox * np.sin(q1_2) - oy * np.cos(q1_2), ny * np.cos(q1_2) - nx * np.sin(q1_2)) + np.pi
    34. # 求解q5
    35. # 见论文公式(2.24)
    36. if ay * np.cos(q1_1) - ax * np.sin(q1_1) > 1:
    37. q5_1 = False
    38. q5_2 = False
    39. else:
    40. q5_1 = np.arccos(ay * np.cos(q1_1) - ax * np.sin(q1_1))
    41. q5_2 = -q5_1
    42. if ay * np.cos(q1_2) - ax * np.sin(q1_2) > 1:
    43. q5_3 = False
    44. q5_4 = False
    45. else:
    46. q5_3 = np.arccos(ay * np.cos(q1_2) - ax * np.sin(q1_2))
    47. q5_4 = -q5_3
    48. # 求解q3
    49. # 见论文公式(2.40)
    50. # 如果arccos()中的值大于1,会出现nan的结果,报错:RuntimeWarning: invalid value encountered in arccos
    51. if q5_1 == 0:
    52. m1 = 10000
    53. else:
    54. m1 = px * np.cos(q1_1) + py * np.sin(q1_1) - d5 * az / np.sin(q5_1) - d6 * (
    55. ax * np.cos(q1_1) + ay * np.sin(q1_1))
    56. if q5_2 == 0:
    57. m2 = 10000
    58. else:
    59. m2 = px * np.cos(q1_1) + py * np.sin(q1_1) - d5 * az / np.sin(q5_2) - d6 * (
    60. ax * np.cos(q1_1) + ay * np.sin(q1_1))
    61. if q5_3 == 0:
    62. m3 = 10000
    63. else:
    64. m3 = px * np.cos(q1_2) + py * np.sin(q1_2) - d5 * az / np.sin(q5_3) - d6 * (
    65. ax * np.cos(q1_2) + ay * np.sin(q1_2))
    66. if q5_4 == 0:
    67. m4 = 10000
    68. else:
    69. m4 = px * np.cos(q1_2) + py * np.sin(q1_2) - d5 * az / np.sin(q5_4) - d6 * (
    70. ax * np.cos(q1_2) + ay * np.sin(q1_2))
    71. if q5_1 == 0:
    72. n1 = 10000
    73. else:
    74. n1 = pz - d1 - d6 * az + d5 / np.sin(q5_1) * (ax * np.cos(q1_1) + ay * np.sin(q1_1))
    75. if q5_2 == 0:
    76. n2 = 10000
    77. else:
    78. n2 = pz - d1 - d6 * az + d5 / np.sin(q5_2) * (ax * np.cos(q1_1) + ay * np.sin(q1_1))
    79. if q5_3 == 0:
    80. n3 = 10000
    81. else:
    82. n3 = pz - d1 - d6 * az + d5 / np.sin(q5_3) * (ax * np.cos(q1_2) + ay * np.sin(q1_2))
    83. if q5_4 == 0:
    84. n4 = 10000
    85. else:
    86. n4 = pz - d1 - d6 * az + d5 / np.sin(q5_4) * (ax * np.cos(q1_2) + ay * np.sin(q1_2))
    87. if (m1 ** 2 + n1 ** 2 - a2 ** 2 - a3 ** 2) / (2 * a2 * a3) > 1 or (m1 ** 2 + n1 ** 2 - a2 ** 2 - a3 ** 2) / (
    88. 2 * a2 * a3) < -1:
    89. q3_1 = False
    90. q3_2 = False
    91. else:
    92. q3_1 = np.arccos((m1 ** 2 + n1 ** 2 - a2 ** 2 - a3 ** 2) / (2 * a2 * a3))
    93. q3_2 = -q3_1
    94. if (m2 ** 2 + n2 ** 2 - a2 ** 2 - a3 ** 2) / (2 * a2 * a3) > 1 or (m2 ** 2 + n2 ** 2 - a2 ** 2 - a3 ** 2) / (
    95. 2 * a2 * a3) < -1:
    96. q3_3 = False
    97. q3_4 = False
    98. else:
    99. q3_3 = np.arccos((m2 ** 2 + n2 ** 2 - a2 ** 2 - a3 ** 2) / (2 * a2 * a3))
    100. q3_4 = -q3_3
    101. if (m3 ** 2 + n3 ** 2 - a2 ** 2 - a3 ** 2) / (2 * a2 * a3) > 1 or (m3 ** 2 + n3 ** 2 - a2 ** 2 - a3 ** 2) / (
    102. 2 * a2 * a3) < -1:
    103. q3_5 = False
    104. q3_6 = False
    105. else:
    106. q3_5 = np.arccos((m3 ** 2 + n3 ** 2 - a2 ** 2 - a3 ** 2) / (2 * a2 * a3))
    107. q3_6 = -q3_5
    108. if (m4 ** 2 + n4 ** 2 - a2 ** 2 - a3 ** 2) / (2 * a2 * a3) > 1 or (m4 ** 2 + n4 ** 2 - a2 ** 2 - a3 ** 2) / (
    109. 2 * a2 * a3) < -1:
    110. q3_7 = False
    111. q3_8 = False
    112. else:
    113. q3_7 = np.arccos((m4 ** 2 + n4 ** 2 - a2 ** 2 - a3 ** 2) / (2 * a2 * a3))
    114. q3_8 = -q3_7
    115. # 求解q2
    116. # 见论文公式(2.43)
    117. if not q3_1:
    118. q2_1 = False
    119. q2_2 = False
    120. else:
    121. q2_1 = 2 * np.arctan2(
    122. -a3 * np.sin(q3_1) + np.sqrt((-a3 * np.sin(q3_1)) ** 2 + (a2 + a3 * np.cos(q3_1)) ** 2 - m1 ** 2),
    123. a2 + a3 * np.cos(q3_1) + m1)
    124. q2_2 = 2 * np.arctan2(
    125. -a3 * np.sin(q3_1) - np.sqrt((-a3 * np.sin(q3_1)) ** 2 + (a2 + a3 * np.cos(q3_1)) ** 2 - m1 ** 2),
    126. a2 + a3 * np.cos(q3_1) + m1)
    127. if not q3_2:
    128. q2_3 = False
    129. q2_4 = False
    130. else:
    131. q2_3 = 2 * np.arctan2(
    132. -a3 * np.sin(q3_2) + np.sqrt((-a3 * np.sin(q3_2)) ** 2 + (a2 + a3 * np.cos(q3_2)) ** 2 - m1 ** 2),
    133. a2 + a3 * np.cos(q3_2) + m1)
    134. q2_4 = 2 * np.arctan2(
    135. -a3 * np.sin(q3_2) - np.sqrt((-a3 * np.sin(q3_2)) ** 2 + (a2 + a3 * np.cos(q3_2)) ** 2 - m1 ** 2),
    136. a2 + a3 * np.cos(q3_2) + m1)
    137. if not q3_3:
    138. q2_5 = False
    139. q2_6 = False
    140. else:
    141. q2_5 = 2 * np.arctan2(
    142. -a3 * np.sin(q3_3) + np.sqrt((-a3 * np.sin(q3_3)) ** 2 + (a2 + a3 * np.cos(q3_3)) ** 2 - m2 ** 2),
    143. a2 + a3 * np.cos(q3_3) + m2)
    144. q2_6 = 2 * np.arctan2(
    145. -a3 * np.sin(q3_3) - np.sqrt((-a3 * np.sin(q3_3)) ** 2 + (a2 + a3 * np.cos(q3_3)) ** 2 - m2 ** 2),
    146. a2 + a3 * np.cos(q3_3) + m2)
    147. if not q3_4:
    148. q2_7 = False
    149. q2_8 = False
    150. else:
    151. q2_7 = 2 * np.arctan2(
    152. -a3 * np.sin(q3_4) + np.sqrt((-a3 * np.sin(q3_4)) ** 2 + (a2 + a3 * np.cos(q3_4)) ** 2 - m2 ** 2),
    153. a2 + a3 * np.cos(q3_4) + m2)
    154. q2_8 = 2 * np.arctan2(
    155. -a3 * np.sin(q3_4) - np.sqrt((-a3 * np.sin(q3_4)) ** 2 + (a2 + a3 * np.cos(q3_4)) ** 2 - m2 ** 2),
    156. a2 + a3 * np.cos(q3_4) + m2)
    157. if not q3_5:
    158. q2_9 = False
    159. q2_10 = False
    160. else:
    161. q2_9 = 2 * np.arctan2(
    162. -a3 * np.sin(q3_5) + np.sqrt((-a3 * np.sin(q3_5)) ** 2 + (a2 + a3 * np.cos(q3_5)) ** 2 - m3 ** 2),
    163. a2 + a3 * np.cos(q3_5) + m3)
    164. q2_10 = 2 * np.arctan2(
    165. -a3 * np.sin(q3_5) - np.sqrt((-a3 * np.sin(q3_5)) ** 2 + (a2 + a3 * np.cos(q3_5)) ** 2 - m3 ** 2),
    166. a2 + a3 * np.cos(q3_5) + m3)
    167. if not q3_6:
    168. q2_11 = False
    169. q2_12 = False
    170. else:
    171. q2_11 = 2 * np.arctan2(
    172. -a3 * np.sin(q3_6) + np.sqrt((-a3 * np.sin(q3_6)) ** 2 + (a2 + a3 * np.cos(q3_6)) ** 2 - m3 ** 2),
    173. a2 + a3 * np.cos(q3_6) + m3)
    174. q2_12 = 2 * np.arctan2(
    175. -a3 * np.sin(q3_6) - np.sqrt((-a3 * np.sin(q3_6)) ** 2 + (a2 + a3 * np.cos(q3_6)) ** 2 - m3 ** 2),
    176. a2 + a3 * np.cos(q3_6) + m3)
    177. if not q3_7:
    178. q2_13 = False
    179. q2_14 = False
    180. else:
    181. q2_13 = 2 * np.arctan2(
    182. -a3 * np.sin(q3_7) + np.sqrt((-a3 * np.sin(q3_7)) ** 2 + (a2 + a3 * np.cos(q3_7)) ** 2 - m4 ** 2),
    183. a2 + a3 * np.cos(q3_7) + m4)
    184. q2_14 = 2 * np.arctan2(
    185. -a3 * np.sin(q3_7) - np.sqrt((-a3 * np.sin(q3_7)) ** 2 + (a2 + a3 * np.cos(q3_7)) ** 2 - m4 ** 2),
    186. a2 + a3 * np.cos(q3_7) + m4)
    187. if not q3_8:
    188. q2_15 = False
    189. q2_16 = False
    190. else:
    191. q2_15 = 2 * np.arctan2(
    192. -a3 * np.sin(q3_8) + np.sqrt((-a3 * np.sin(q3_8)) ** 2 + (a2 + a3 * np.cos(q3_8)) ** 2 - m4 ** 2),
    193. a2 + a3 * np.cos(q3_8) + m4)
    194. q2_16 = 2 * np.arctan2(
    195. -a3 * np.sin(q3_8) - np.sqrt((-a3 * np.sin(q3_8)) ** 2 + (a2 + a3 * np.cos(q3_8)) ** 2 - m4 ** 2),
    196. a2 + a3 * np.cos(q3_8) + m4)
    197. # 求解q4
    198. # 见论文公式(2.46)
    199. if not q3_1:
    200. q4_1 = False
    201. q4_2 = False
    202. else:
    203. q4_1 = np.arctan2(az, ax * np.cos(q1_1) + ay * np.sin(q1_1)) - q3_1 - q2_1
    204. q4_2 = np.arctan2(az, ax * np.cos(q1_1) + ay * np.sin(q1_1)) - q3_1 - q2_2
    205. if q4_1 > np.pi:
    206. q4_1 = q4_1 - np.pi
    207. elif q4_1 < -np.pi:
    208. q4_1 = q4_1 + np.pi
    209. if q4_2 > np.pi:
    210. q4_2 = q4_2 - np.pi
    211. elif q4_2 < -np.pi:
    212. q4_2 = q4_2 + np.pi
    213. if not q3_2:
    214. q4_3 = False
    215. q4_4 = False
    216. else:
    217. q4_3 = np.arctan2(az, ax * np.cos(q1_1) + ay * np.sin(q1_1)) - q3_2 - q2_3
    218. q4_4 = np.arctan2(az, ax * np.cos(q1_1) + ay * np.sin(q1_1)) - q3_2 - q2_4
    219. if q4_3 > np.pi:
    220. q4_3 = q4_3 - np.pi
    221. elif q4_3 < -np.pi:
    222. q4_3 = q4_3 + np.pi
    223. if q4_4 > np.pi:
    224. q4_4 = q4_4 - np.pi
    225. elif q4_4 < -np.pi:
    226. q4_4 = q4_4 + np.pi
    227. if not q3_3:
    228. q4_5 = False
    229. q4_6 = False
    230. else:
    231. q4_5 = np.arctan2(az, ax * np.cos(q1_1) + ay * np.sin(q1_1)) - q3_3 - q2_5
    232. q4_6 = np.arctan2(az, ax * np.cos(q1_1) + ay * np.sin(q1_1)) - q3_3 - q2_6
    233. if q4_5 > np.pi:
    234. q4_5 = q4_5 - np.pi
    235. elif q4_5 < -np.pi:
    236. q4_5 = q4_5 + np.pi
    237. if q4_6 > np.pi:
    238. q4_6 = q4_6 - np.pi
    239. elif q4_6 < -np.pi:
    240. q4_6 = q4_6 + np.pi
    241. if not q3_4:
    242. q4_7 = False
    243. q4_8 = False
    244. else:
    245. q4_7 = np.arctan2(az, ax * np.cos(q1_1) + ay * np.sin(q1_1)) - q3_4 - q2_7
    246. q4_8 = np.arctan2(az, ax * np.cos(q1_1) + ay * np.sin(q1_1)) - q3_4 - q2_8
    247. if q4_7 > np.pi:
    248. q4_7 = q4_7 - np.pi
    249. elif q4_7 < -np.pi:
    250. q4_7 = q4_7 + np.pi
    251. if q4_8 > np.pi:
    252. q4_8 = q4_8 - np.pi
    253. elif q4_8 < -np.pi:
    254. q4_8 = q4_8 + np.pi
    255. if not q3_5:
    256. q4_9 = False
    257. q4_10 = False
    258. else:
    259. q4_9 = np.arctan2(az, ax * np.cos(q1_2) + ay * np.sin(q1_2)) - q3_5 - q2_9
    260. q4_10 = np.arctan2(az, ax * np.cos(q1_2) + ay * np.sin(q1_2)) - q3_5 - q2_10
    261. if q4_9 > np.pi:
    262. q4_9 = q4_9 - np.pi
    263. elif q4_9 < -np.pi:
    264. q4_9 = q4_9 + np.pi
    265. if q4_10 > np.pi:
    266. q4_10 = q4_10 - np.pi
    267. elif q4_10 < -np.pi:
    268. q4_10 = q4_10 + np.pi
    269. if not q3_6:
    270. q4_11 = False
    271. q4_12 = False
    272. else:
    273. q4_11 = np.arctan2(az, ax * np.cos(q1_2) + ay * np.sin(q1_2)) - q3_6 - q2_11
    274. q4_12 = np.arctan2(az, ax * np.cos(q1_2) + ay * np.sin(q1_2)) - q3_6 - q2_12
    275. if q4_11 > np.pi:
    276. q4_11 = q4_11 - np.pi
    277. elif q4_11 < -np.pi:
    278. q4_11 = q4_11 + np.pi
    279. if q4_12 > np.pi:
    280. q4_12 = q4_12 - np.pi
    281. elif q4_12 < -np.pi:
    282. q4_12 = q4_12 + np.pi
    283. if not q3_7:
    284. q4_13 = False
    285. q4_14 = False
    286. else:
    287. q4_13 = np.arctan2(az, ax * np.cos(q1_2) + ay * np.sin(q1_2)) - q3_7 - q2_13
    288. q4_14 = np.arctan2(az, ax * np.cos(q1_2) + ay * np.sin(q1_2)) - q3_7 - q2_14
    289. if q4_13 > np.pi:
    290. q4_13 = q4_13 - np.pi
    291. elif q4_13 < -np.pi:
    292. q4_13 = q4_13 + np.pi
    293. if q4_14 > np.pi:
    294. q4_14 = q4_14 - np.pi
    295. elif q4_14 < -np.pi:
    296. q4_14 = q4_14 + np.pi
    297. if not q3_8:
    298. q4_15 = False
    299. q4_16 = False
    300. else:
    301. q4_15 = np.arctan2(az, ax * np.cos(q1_2) + ay * np.sin(q1_2)) - q3_8 - q2_15
    302. q4_16 = np.arctan2(az, ax * np.cos(q1_2) + ay * np.sin(q1_2)) - q3_8 - q2_16
    303. if q4_15 > np.pi:
    304. q4_15 = q4_15 - np.pi
    305. elif q4_15 < -np.pi:
    306. q4_15 = q4_15 + np.pi
    307. if q4_16 > np.pi:
    308. q4_16 = q4_16 - np.pi
    309. elif q4_16 < -np.pi:
    310. q4_16 = q4_16 + np.pi
    311. ikine_1 = [q1_1, q2_1, q3_1, q4_1, q5_1, q6_1]
    312. ikine_2 = [q1_1, q2_2, q3_1, q4_2, q5_1, q6_1]
    313. ikine_3 = [q1_1, q2_3, q3_2, q4_3, q5_1, q6_1]
    314. ikine_4 = [q1_1, q2_4, q3_2, q4_4, q5_1, q6_1]
    315. ikine_5 = [q1_1, q2_5, q3_3, q4_5, q5_2, q6_1]
    316. ikine_6 = [q1_1, q2_6, q3_3, q4_6, q5_2, q6_1]
    317. ikine_7 = [q1_1, q2_7, q3_4, q4_7, q5_2, q6_1]
    318. ikine_8 = [q1_1, q2_8, q3_4, q4_8, q5_2, q6_1]
    319. ikine_9 = [q1_2, q2_9, q3_5, q4_9, q5_3, q6_2]
    320. ikine_10 = [q1_2, q2_10, q3_5, q4_10, q5_3, q6_2]
    321. ikine_11 = [q1_2, q2_11, q3_6, q4_11, q5_3, q6_2]
    322. ikine_12 = [q1_2, q2_12, q3_6, q4_12, q5_3, q6_2]
    323. ikine_13 = [q1_2, q2_13, q3_7, q4_13, q5_4, q6_2]
    324. ikine_14 = [q1_2, q2_14, q3_7, q4_14, q5_4, q6_2]
    325. ikine_15 = [q1_2, q2_15, q3_8, q4_15, q5_4, q6_2]
    326. ikine_16 = [q1_2, q2_16, q3_8, q4_16, q5_4, q6_2]
    327. q_ikine_list = []
    328. q_ikine_list_all = [ikine_1,
    329. ikine_2,
    330. ikine_3,
    331. ikine_4,
    332. ikine_5,
    333. ikine_6,
    334. ikine_7,
    335. ikine_8,
    336. ikine_9,
    337. ikine_10,
    338. ikine_11,
    339. ikine_12,
    340. ikine_13,
    341. ikine_14,
    342. ikine_15,
    343. ikine_16]
    344. for one_q_ikinelist in q_ikine_list_all:
    345. for count, q in enumerate(one_q_ikinelist):
    346. if not q:
    347. one_q_ikinelist = None
    348. break
    349. if q < q_range[count][0]/np.pi*180 or q > q_range[count][1]/np.pi*180:
    350. one_q_ikinelist = None
    351. print(one_q_ikinelist)
    352. break
    353. if one_q_ikinelist is not None:
    354. q_ikine_list.append(one_q_ikinelist)
    355. return q_ikine_list

    ……具体的解一共有十六个,但是不是每一个值都是有效的,则需要我们去鉴别!

    但是我也不是很会取舍其中的解析解,我认为从以下几方面考虑:

    奇异解位置、关节角约束、性能约束……

    时间最优、能量最优、路径最优……

  • 相关阅读:
    【数据结构----KMP算法】校招笔试题总结
    【数字信号去噪】小波软阈值+硬阈值+改进阈值数字信号去噪【含Matlab源码 1025期】
    【web-渗透测试方法】(15.4)测试会话管理机制
    为什么不建议库导出c++接口
    数据可视化之大数据平台可视化
    Linux内核互斥技术1
    跨境电商在电商行业中是否还有立足之地?
    理论辐照度计算
    anaconda环境更改gcc版本并编译Pytorch3D 0.4.0
    C++编程题目2
  • 原文地址:https://blog.csdn.net/weixin_44917390/article/details/125438674