mink 0.0.1__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.
Files changed (352) hide show
  1. mink/.mypy_cache/.gitignore +2 -0
  2. mink/.mypy_cache/3.12/@plugins_snapshot.json +1 -0
  3. mink/.mypy_cache/3.12/__future__.data.json +1 -0
  4. mink/.mypy_cache/3.12/__future__.meta.json +1 -0
  5. mink/.mypy_cache/3.12/_ast.data.json +1 -0
  6. mink/.mypy_cache/3.12/_ast.meta.json +1 -0
  7. mink/.mypy_cache/3.12/_codecs.data.json +1 -0
  8. mink/.mypy_cache/3.12/_codecs.meta.json +1 -0
  9. mink/.mypy_cache/3.12/_collections_abc.data.json +1 -0
  10. mink/.mypy_cache/3.12/_collections_abc.meta.json +1 -0
  11. mink/.mypy_cache/3.12/_ctypes.data.json +1 -0
  12. mink/.mypy_cache/3.12/_ctypes.meta.json +1 -0
  13. mink/.mypy_cache/3.12/_thread.data.json +1 -0
  14. mink/.mypy_cache/3.12/_thread.meta.json +1 -0
  15. mink/.mypy_cache/3.12/_typeshed/__init__.data.json +1 -0
  16. mink/.mypy_cache/3.12/_typeshed/__init__.meta.json +1 -0
  17. mink/.mypy_cache/3.12/_warnings.data.json +1 -0
  18. mink/.mypy_cache/3.12/_warnings.meta.json +1 -0
  19. mink/.mypy_cache/3.12/abc.data.json +1 -0
  20. mink/.mypy_cache/3.12/abc.meta.json +1 -0
  21. mink/.mypy_cache/3.12/array.data.json +1 -0
  22. mink/.mypy_cache/3.12/array.meta.json +1 -0
  23. mink/.mypy_cache/3.12/ast.data.json +1 -0
  24. mink/.mypy_cache/3.12/ast.meta.json +1 -0
  25. mink/.mypy_cache/3.12/builtins.data.json +1 -0
  26. mink/.mypy_cache/3.12/builtins.meta.json +1 -0
  27. mink/.mypy_cache/3.12/codecs.data.json +1 -0
  28. mink/.mypy_cache/3.12/codecs.meta.json +1 -0
  29. mink/.mypy_cache/3.12/collections/__init__.data.json +1 -0
  30. mink/.mypy_cache/3.12/collections/__init__.meta.json +1 -0
  31. mink/.mypy_cache/3.12/collections/abc.data.json +1 -0
  32. mink/.mypy_cache/3.12/collections/abc.meta.json +1 -0
  33. mink/.mypy_cache/3.12/contextlib.data.json +1 -0
  34. mink/.mypy_cache/3.12/contextlib.meta.json +1 -0
  35. mink/.mypy_cache/3.12/ctypes/__init__.data.json +1 -0
  36. mink/.mypy_cache/3.12/ctypes/__init__.meta.json +1 -0
  37. mink/.mypy_cache/3.12/dataclasses.data.json +1 -0
  38. mink/.mypy_cache/3.12/dataclasses.meta.json +1 -0
  39. mink/.mypy_cache/3.12/datetime.data.json +1 -0
  40. mink/.mypy_cache/3.12/datetime.meta.json +1 -0
  41. mink/.mypy_cache/3.12/email/__init__.data.json +1 -0
  42. mink/.mypy_cache/3.12/email/__init__.meta.json +1 -0
  43. mink/.mypy_cache/3.12/email/charset.data.json +1 -0
  44. mink/.mypy_cache/3.12/email/charset.meta.json +1 -0
  45. mink/.mypy_cache/3.12/email/contentmanager.data.json +1 -0
  46. mink/.mypy_cache/3.12/email/contentmanager.meta.json +1 -0
  47. mink/.mypy_cache/3.12/email/errors.data.json +1 -0
  48. mink/.mypy_cache/3.12/email/errors.meta.json +1 -0
  49. mink/.mypy_cache/3.12/email/header.data.json +1 -0
  50. mink/.mypy_cache/3.12/email/header.meta.json +1 -0
  51. mink/.mypy_cache/3.12/email/message.data.json +1 -0
  52. mink/.mypy_cache/3.12/email/message.meta.json +1 -0
  53. mink/.mypy_cache/3.12/email/policy.data.json +1 -0
  54. mink/.mypy_cache/3.12/email/policy.meta.json +1 -0
  55. mink/.mypy_cache/3.12/enum.data.json +1 -0
  56. mink/.mypy_cache/3.12/enum.meta.json +1 -0
  57. mink/.mypy_cache/3.12/genericpath.data.json +1 -0
  58. mink/.mypy_cache/3.12/genericpath.meta.json +1 -0
  59. mink/.mypy_cache/3.12/importlib/__init__.data.json +1 -0
  60. mink/.mypy_cache/3.12/importlib/__init__.meta.json +1 -0
  61. mink/.mypy_cache/3.12/importlib/abc.data.json +1 -0
  62. mink/.mypy_cache/3.12/importlib/abc.meta.json +1 -0
  63. mink/.mypy_cache/3.12/importlib/machinery.data.json +1 -0
  64. mink/.mypy_cache/3.12/importlib/machinery.meta.json +1 -0
  65. mink/.mypy_cache/3.12/importlib/metadata/__init__.data.json +1 -0
  66. mink/.mypy_cache/3.12/importlib/metadata/__init__.meta.json +1 -0
  67. mink/.mypy_cache/3.12/importlib/metadata/_meta.data.json +1 -0
  68. mink/.mypy_cache/3.12/importlib/metadata/_meta.meta.json +1 -0
  69. mink/.mypy_cache/3.12/importlib/readers.data.json +1 -0
  70. mink/.mypy_cache/3.12/importlib/readers.meta.json +1 -0
  71. mink/.mypy_cache/3.12/importlib/resources/__init__.data.json +1 -0
  72. mink/.mypy_cache/3.12/importlib/resources/__init__.meta.json +1 -0
  73. mink/.mypy_cache/3.12/importlib/resources/abc.data.json +1 -0
  74. mink/.mypy_cache/3.12/importlib/resources/abc.meta.json +1 -0
  75. mink/.mypy_cache/3.12/io.data.json +1 -0
  76. mink/.mypy_cache/3.12/io.meta.json +1 -0
  77. mink/.mypy_cache/3.12/logging/__init__.data.json +1 -0
  78. mink/.mypy_cache/3.12/logging/__init__.meta.json +1 -0
  79. mink/.mypy_cache/3.12/math.data.json +1 -0
  80. mink/.mypy_cache/3.12/math.meta.json +1 -0
  81. mink/.mypy_cache/3.12/mink/limits/limit.data.json +1 -0
  82. mink/.mypy_cache/3.12/mink/limits/limit.meta.json +1 -0
  83. mink/.mypy_cache/3.12/mmap.data.json +1 -0
  84. mink/.mypy_cache/3.12/mmap.meta.json +1 -0
  85. mink/.mypy_cache/3.12/numpy/__init__.data.json +1 -0
  86. mink/.mypy_cache/3.12/numpy/__init__.meta.json +1 -0
  87. mink/.mypy_cache/3.12/numpy/_pytesttester.data.json +1 -0
  88. mink/.mypy_cache/3.12/numpy/_pytesttester.meta.json +1 -0
  89. mink/.mypy_cache/3.12/numpy/_typing/__init__.data.json +1 -0
  90. mink/.mypy_cache/3.12/numpy/_typing/__init__.meta.json +1 -0
  91. mink/.mypy_cache/3.12/numpy/_typing/_add_docstring.data.json +1 -0
  92. mink/.mypy_cache/3.12/numpy/_typing/_add_docstring.meta.json +1 -0
  93. mink/.mypy_cache/3.12/numpy/_typing/_array_like.data.json +1 -0
  94. mink/.mypy_cache/3.12/numpy/_typing/_array_like.meta.json +1 -0
  95. mink/.mypy_cache/3.12/numpy/_typing/_callable.data.json +1 -0
  96. mink/.mypy_cache/3.12/numpy/_typing/_callable.meta.json +1 -0
  97. mink/.mypy_cache/3.12/numpy/_typing/_char_codes.data.json +1 -0
  98. mink/.mypy_cache/3.12/numpy/_typing/_char_codes.meta.json +1 -0
  99. mink/.mypy_cache/3.12/numpy/_typing/_dtype_like.data.json +1 -0
  100. mink/.mypy_cache/3.12/numpy/_typing/_dtype_like.meta.json +1 -0
  101. mink/.mypy_cache/3.12/numpy/_typing/_extended_precision.data.json +1 -0
  102. mink/.mypy_cache/3.12/numpy/_typing/_extended_precision.meta.json +1 -0
  103. mink/.mypy_cache/3.12/numpy/_typing/_nbit.data.json +1 -0
  104. mink/.mypy_cache/3.12/numpy/_typing/_nbit.meta.json +1 -0
  105. mink/.mypy_cache/3.12/numpy/_typing/_nested_sequence.data.json +1 -0
  106. mink/.mypy_cache/3.12/numpy/_typing/_nested_sequence.meta.json +1 -0
  107. mink/.mypy_cache/3.12/numpy/_typing/_scalars.data.json +1 -0
  108. mink/.mypy_cache/3.12/numpy/_typing/_scalars.meta.json +1 -0
  109. mink/.mypy_cache/3.12/numpy/_typing/_shape.data.json +1 -0
  110. mink/.mypy_cache/3.12/numpy/_typing/_shape.meta.json +1 -0
  111. mink/.mypy_cache/3.12/numpy/_typing/_ufunc.data.json +1 -0
  112. mink/.mypy_cache/3.12/numpy/_typing/_ufunc.meta.json +1 -0
  113. mink/.mypy_cache/3.12/numpy/_utils/__init__.data.json +1 -0
  114. mink/.mypy_cache/3.12/numpy/_utils/__init__.meta.json +1 -0
  115. mink/.mypy_cache/3.12/numpy/_utils/_convertions.data.json +1 -0
  116. mink/.mypy_cache/3.12/numpy/_utils/_convertions.meta.json +1 -0
  117. mink/.mypy_cache/3.12/numpy/core/__init__.data.json +1 -0
  118. mink/.mypy_cache/3.12/numpy/core/__init__.meta.json +1 -0
  119. mink/.mypy_cache/3.12/numpy/core/_asarray.data.json +1 -0
  120. mink/.mypy_cache/3.12/numpy/core/_asarray.meta.json +1 -0
  121. mink/.mypy_cache/3.12/numpy/core/_internal.data.json +1 -0
  122. mink/.mypy_cache/3.12/numpy/core/_internal.meta.json +1 -0
  123. mink/.mypy_cache/3.12/numpy/core/_type_aliases.data.json +1 -0
  124. mink/.mypy_cache/3.12/numpy/core/_type_aliases.meta.json +1 -0
  125. mink/.mypy_cache/3.12/numpy/core/_ufunc_config.data.json +1 -0
  126. mink/.mypy_cache/3.12/numpy/core/_ufunc_config.meta.json +1 -0
  127. mink/.mypy_cache/3.12/numpy/core/arrayprint.data.json +1 -0
  128. mink/.mypy_cache/3.12/numpy/core/arrayprint.meta.json +1 -0
  129. mink/.mypy_cache/3.12/numpy/core/defchararray.data.json +1 -0
  130. mink/.mypy_cache/3.12/numpy/core/defchararray.meta.json +1 -0
  131. mink/.mypy_cache/3.12/numpy/core/einsumfunc.data.json +1 -0
  132. mink/.mypy_cache/3.12/numpy/core/einsumfunc.meta.json +1 -0
  133. mink/.mypy_cache/3.12/numpy/core/fromnumeric.data.json +1 -0
  134. mink/.mypy_cache/3.12/numpy/core/fromnumeric.meta.json +1 -0
  135. mink/.mypy_cache/3.12/numpy/core/function_base.data.json +1 -0
  136. mink/.mypy_cache/3.12/numpy/core/function_base.meta.json +1 -0
  137. mink/.mypy_cache/3.12/numpy/core/multiarray.data.json +1 -0
  138. mink/.mypy_cache/3.12/numpy/core/multiarray.meta.json +1 -0
  139. mink/.mypy_cache/3.12/numpy/core/numeric.data.json +1 -0
  140. mink/.mypy_cache/3.12/numpy/core/numeric.meta.json +1 -0
  141. mink/.mypy_cache/3.12/numpy/core/numerictypes.data.json +1 -0
  142. mink/.mypy_cache/3.12/numpy/core/numerictypes.meta.json +1 -0
  143. mink/.mypy_cache/3.12/numpy/core/records.data.json +1 -0
  144. mink/.mypy_cache/3.12/numpy/core/records.meta.json +1 -0
  145. mink/.mypy_cache/3.12/numpy/core/shape_base.data.json +1 -0
  146. mink/.mypy_cache/3.12/numpy/core/shape_base.meta.json +1 -0
  147. mink/.mypy_cache/3.12/numpy/core/umath.data.json +1 -0
  148. mink/.mypy_cache/3.12/numpy/core/umath.meta.json +1 -0
  149. mink/.mypy_cache/3.12/numpy/ctypeslib.data.json +1 -0
  150. mink/.mypy_cache/3.12/numpy/ctypeslib.meta.json +1 -0
  151. mink/.mypy_cache/3.12/numpy/dtypes.data.json +1 -0
  152. mink/.mypy_cache/3.12/numpy/dtypes.meta.json +1 -0
  153. mink/.mypy_cache/3.12/numpy/exceptions.data.json +1 -0
  154. mink/.mypy_cache/3.12/numpy/exceptions.meta.json +1 -0
  155. mink/.mypy_cache/3.12/numpy/fft/__init__.data.json +1 -0
  156. mink/.mypy_cache/3.12/numpy/fft/__init__.meta.json +1 -0
  157. mink/.mypy_cache/3.12/numpy/fft/_pocketfft.data.json +1 -0
  158. mink/.mypy_cache/3.12/numpy/fft/_pocketfft.meta.json +1 -0
  159. mink/.mypy_cache/3.12/numpy/fft/helper.data.json +1 -0
  160. mink/.mypy_cache/3.12/numpy/fft/helper.meta.json +1 -0
  161. mink/.mypy_cache/3.12/numpy/lib/__init__.data.json +1 -0
  162. mink/.mypy_cache/3.12/numpy/lib/__init__.meta.json +1 -0
  163. mink/.mypy_cache/3.12/numpy/lib/_version.data.json +1 -0
  164. mink/.mypy_cache/3.12/numpy/lib/_version.meta.json +1 -0
  165. mink/.mypy_cache/3.12/numpy/lib/arraypad.data.json +1 -0
  166. mink/.mypy_cache/3.12/numpy/lib/arraypad.meta.json +1 -0
  167. mink/.mypy_cache/3.12/numpy/lib/arraysetops.data.json +1 -0
  168. mink/.mypy_cache/3.12/numpy/lib/arraysetops.meta.json +1 -0
  169. mink/.mypy_cache/3.12/numpy/lib/arrayterator.data.json +1 -0
  170. mink/.mypy_cache/3.12/numpy/lib/arrayterator.meta.json +1 -0
  171. mink/.mypy_cache/3.12/numpy/lib/format.data.json +1 -0
  172. mink/.mypy_cache/3.12/numpy/lib/format.meta.json +1 -0
  173. mink/.mypy_cache/3.12/numpy/lib/function_base.data.json +1 -0
  174. mink/.mypy_cache/3.12/numpy/lib/function_base.meta.json +1 -0
  175. mink/.mypy_cache/3.12/numpy/lib/histograms.data.json +1 -0
  176. mink/.mypy_cache/3.12/numpy/lib/histograms.meta.json +1 -0
  177. mink/.mypy_cache/3.12/numpy/lib/index_tricks.data.json +1 -0
  178. mink/.mypy_cache/3.12/numpy/lib/index_tricks.meta.json +1 -0
  179. mink/.mypy_cache/3.12/numpy/lib/mixins.data.json +1 -0
  180. mink/.mypy_cache/3.12/numpy/lib/mixins.meta.json +1 -0
  181. mink/.mypy_cache/3.12/numpy/lib/nanfunctions.data.json +1 -0
  182. mink/.mypy_cache/3.12/numpy/lib/nanfunctions.meta.json +1 -0
  183. mink/.mypy_cache/3.12/numpy/lib/npyio.data.json +1 -0
  184. mink/.mypy_cache/3.12/numpy/lib/npyio.meta.json +1 -0
  185. mink/.mypy_cache/3.12/numpy/lib/polynomial.data.json +1 -0
  186. mink/.mypy_cache/3.12/numpy/lib/polynomial.meta.json +1 -0
  187. mink/.mypy_cache/3.12/numpy/lib/scimath.data.json +1 -0
  188. mink/.mypy_cache/3.12/numpy/lib/scimath.meta.json +1 -0
  189. mink/.mypy_cache/3.12/numpy/lib/shape_base.data.json +1 -0
  190. mink/.mypy_cache/3.12/numpy/lib/shape_base.meta.json +1 -0
  191. mink/.mypy_cache/3.12/numpy/lib/stride_tricks.data.json +1 -0
  192. mink/.mypy_cache/3.12/numpy/lib/stride_tricks.meta.json +1 -0
  193. mink/.mypy_cache/3.12/numpy/lib/twodim_base.data.json +1 -0
  194. mink/.mypy_cache/3.12/numpy/lib/twodim_base.meta.json +1 -0
  195. mink/.mypy_cache/3.12/numpy/lib/type_check.data.json +1 -0
  196. mink/.mypy_cache/3.12/numpy/lib/type_check.meta.json +1 -0
  197. mink/.mypy_cache/3.12/numpy/lib/ufunclike.data.json +1 -0
  198. mink/.mypy_cache/3.12/numpy/lib/ufunclike.meta.json +1 -0
  199. mink/.mypy_cache/3.12/numpy/lib/utils.data.json +1 -0
  200. mink/.mypy_cache/3.12/numpy/lib/utils.meta.json +1 -0
  201. mink/.mypy_cache/3.12/numpy/linalg/__init__.data.json +1 -0
  202. mink/.mypy_cache/3.12/numpy/linalg/__init__.meta.json +1 -0
  203. mink/.mypy_cache/3.12/numpy/linalg/linalg.data.json +1 -0
  204. mink/.mypy_cache/3.12/numpy/linalg/linalg.meta.json +1 -0
  205. mink/.mypy_cache/3.12/numpy/ma/__init__.data.json +1 -0
  206. mink/.mypy_cache/3.12/numpy/ma/__init__.meta.json +1 -0
  207. mink/.mypy_cache/3.12/numpy/ma/core.data.json +1 -0
  208. mink/.mypy_cache/3.12/numpy/ma/core.meta.json +1 -0
  209. mink/.mypy_cache/3.12/numpy/ma/extras.data.json +1 -0
  210. mink/.mypy_cache/3.12/numpy/ma/extras.meta.json +1 -0
  211. mink/.mypy_cache/3.12/numpy/ma/mrecords.data.json +1 -0
  212. mink/.mypy_cache/3.12/numpy/ma/mrecords.meta.json +1 -0
  213. mink/.mypy_cache/3.12/numpy/matrixlib/__init__.data.json +1 -0
  214. mink/.mypy_cache/3.12/numpy/matrixlib/__init__.meta.json +1 -0
  215. mink/.mypy_cache/3.12/numpy/matrixlib/defmatrix.data.json +1 -0
  216. mink/.mypy_cache/3.12/numpy/matrixlib/defmatrix.meta.json +1 -0
  217. mink/.mypy_cache/3.12/numpy/polynomial/__init__.data.json +1 -0
  218. mink/.mypy_cache/3.12/numpy/polynomial/__init__.meta.json +1 -0
  219. mink/.mypy_cache/3.12/numpy/polynomial/_polybase.data.json +1 -0
  220. mink/.mypy_cache/3.12/numpy/polynomial/_polybase.meta.json +1 -0
  221. mink/.mypy_cache/3.12/numpy/polynomial/chebyshev.data.json +1 -0
  222. mink/.mypy_cache/3.12/numpy/polynomial/chebyshev.meta.json +1 -0
  223. mink/.mypy_cache/3.12/numpy/polynomial/hermite.data.json +1 -0
  224. mink/.mypy_cache/3.12/numpy/polynomial/hermite.meta.json +1 -0
  225. mink/.mypy_cache/3.12/numpy/polynomial/hermite_e.data.json +1 -0
  226. mink/.mypy_cache/3.12/numpy/polynomial/hermite_e.meta.json +1 -0
  227. mink/.mypy_cache/3.12/numpy/polynomial/laguerre.data.json +1 -0
  228. mink/.mypy_cache/3.12/numpy/polynomial/laguerre.meta.json +1 -0
  229. mink/.mypy_cache/3.12/numpy/polynomial/legendre.data.json +1 -0
  230. mink/.mypy_cache/3.12/numpy/polynomial/legendre.meta.json +1 -0
  231. mink/.mypy_cache/3.12/numpy/polynomial/polynomial.data.json +1 -0
  232. mink/.mypy_cache/3.12/numpy/polynomial/polynomial.meta.json +1 -0
  233. mink/.mypy_cache/3.12/numpy/polynomial/polyutils.data.json +1 -0
  234. mink/.mypy_cache/3.12/numpy/polynomial/polyutils.meta.json +1 -0
  235. mink/.mypy_cache/3.12/numpy/random/__init__.data.json +1 -0
  236. mink/.mypy_cache/3.12/numpy/random/__init__.meta.json +1 -0
  237. mink/.mypy_cache/3.12/numpy/random/_generator.data.json +1 -0
  238. mink/.mypy_cache/3.12/numpy/random/_generator.meta.json +1 -0
  239. mink/.mypy_cache/3.12/numpy/random/_mt19937.data.json +1 -0
  240. mink/.mypy_cache/3.12/numpy/random/_mt19937.meta.json +1 -0
  241. mink/.mypy_cache/3.12/numpy/random/_pcg64.data.json +1 -0
  242. mink/.mypy_cache/3.12/numpy/random/_pcg64.meta.json +1 -0
  243. mink/.mypy_cache/3.12/numpy/random/_philox.data.json +1 -0
  244. mink/.mypy_cache/3.12/numpy/random/_philox.meta.json +1 -0
  245. mink/.mypy_cache/3.12/numpy/random/_sfc64.data.json +1 -0
  246. mink/.mypy_cache/3.12/numpy/random/_sfc64.meta.json +1 -0
  247. mink/.mypy_cache/3.12/numpy/random/bit_generator.data.json +1 -0
  248. mink/.mypy_cache/3.12/numpy/random/bit_generator.meta.json +1 -0
  249. mink/.mypy_cache/3.12/numpy/random/mtrand.data.json +1 -0
  250. mink/.mypy_cache/3.12/numpy/random/mtrand.meta.json +1 -0
  251. mink/.mypy_cache/3.12/numpy/testing/__init__.data.json +1 -0
  252. mink/.mypy_cache/3.12/numpy/testing/__init__.meta.json +1 -0
  253. mink/.mypy_cache/3.12/numpy/testing/_private/__init__.data.json +1 -0
  254. mink/.mypy_cache/3.12/numpy/testing/_private/__init__.meta.json +1 -0
  255. mink/.mypy_cache/3.12/numpy/testing/_private/utils.data.json +1 -0
  256. mink/.mypy_cache/3.12/numpy/testing/_private/utils.meta.json +1 -0
  257. mink/.mypy_cache/3.12/numpy/typing/__init__.data.json +1 -0
  258. mink/.mypy_cache/3.12/numpy/typing/__init__.meta.json +1 -0
  259. mink/.mypy_cache/3.12/numpy/version.data.json +1 -0
  260. mink/.mypy_cache/3.12/numpy/version.meta.json +1 -0
  261. mink/.mypy_cache/3.12/os/__init__.data.json +1 -0
  262. mink/.mypy_cache/3.12/os/__init__.meta.json +1 -0
  263. mink/.mypy_cache/3.12/os/path.data.json +1 -0
  264. mink/.mypy_cache/3.12/os/path.meta.json +1 -0
  265. mink/.mypy_cache/3.12/pathlib.data.json +1 -0
  266. mink/.mypy_cache/3.12/pathlib.meta.json +1 -0
  267. mink/.mypy_cache/3.12/posixpath.data.json +1 -0
  268. mink/.mypy_cache/3.12/posixpath.meta.json +1 -0
  269. mink/.mypy_cache/3.12/re.data.json +1 -0
  270. mink/.mypy_cache/3.12/re.meta.json +1 -0
  271. mink/.mypy_cache/3.12/sre_compile.data.json +1 -0
  272. mink/.mypy_cache/3.12/sre_compile.meta.json +1 -0
  273. mink/.mypy_cache/3.12/sre_constants.data.json +1 -0
  274. mink/.mypy_cache/3.12/sre_constants.meta.json +1 -0
  275. mink/.mypy_cache/3.12/sre_parse.data.json +1 -0
  276. mink/.mypy_cache/3.12/sre_parse.meta.json +1 -0
  277. mink/.mypy_cache/3.12/string.data.json +1 -0
  278. mink/.mypy_cache/3.12/string.meta.json +1 -0
  279. mink/.mypy_cache/3.12/subprocess.data.json +1 -0
  280. mink/.mypy_cache/3.12/subprocess.meta.json +1 -0
  281. mink/.mypy_cache/3.12/sys/__init__.data.json +1 -0
  282. mink/.mypy_cache/3.12/sys/__init__.meta.json +1 -0
  283. mink/.mypy_cache/3.12/sys/_monitoring.data.json +1 -0
  284. mink/.mypy_cache/3.12/sys/_monitoring.meta.json +1 -0
  285. mink/.mypy_cache/3.12/textwrap.data.json +1 -0
  286. mink/.mypy_cache/3.12/textwrap.meta.json +1 -0
  287. mink/.mypy_cache/3.12/threading.data.json +1 -0
  288. mink/.mypy_cache/3.12/threading.meta.json +1 -0
  289. mink/.mypy_cache/3.12/time.data.json +1 -0
  290. mink/.mypy_cache/3.12/time.meta.json +1 -0
  291. mink/.mypy_cache/3.12/types.data.json +1 -0
  292. mink/.mypy_cache/3.12/types.meta.json +1 -0
  293. mink/.mypy_cache/3.12/typing.data.json +1 -0
  294. mink/.mypy_cache/3.12/typing.meta.json +1 -0
  295. mink/.mypy_cache/3.12/typing_extensions.data.json +1 -0
  296. mink/.mypy_cache/3.12/typing_extensions.meta.json +1 -0
  297. mink/.mypy_cache/3.12/unittest/__init__.data.json +1 -0
  298. mink/.mypy_cache/3.12/unittest/__init__.meta.json +1 -0
  299. mink/.mypy_cache/3.12/unittest/_log.data.json +1 -0
  300. mink/.mypy_cache/3.12/unittest/_log.meta.json +1 -0
  301. mink/.mypy_cache/3.12/unittest/async_case.data.json +1 -0
  302. mink/.mypy_cache/3.12/unittest/async_case.meta.json +1 -0
  303. mink/.mypy_cache/3.12/unittest/case.data.json +1 -0
  304. mink/.mypy_cache/3.12/unittest/case.meta.json +1 -0
  305. mink/.mypy_cache/3.12/unittest/loader.data.json +1 -0
  306. mink/.mypy_cache/3.12/unittest/loader.meta.json +1 -0
  307. mink/.mypy_cache/3.12/unittest/main.data.json +1 -0
  308. mink/.mypy_cache/3.12/unittest/main.meta.json +1 -0
  309. mink/.mypy_cache/3.12/unittest/result.data.json +1 -0
  310. mink/.mypy_cache/3.12/unittest/result.meta.json +1 -0
  311. mink/.mypy_cache/3.12/unittest/runner.data.json +1 -0
  312. mink/.mypy_cache/3.12/unittest/runner.meta.json +1 -0
  313. mink/.mypy_cache/3.12/unittest/signals.data.json +1 -0
  314. mink/.mypy_cache/3.12/unittest/signals.meta.json +1 -0
  315. mink/.mypy_cache/3.12/unittest/suite.data.json +1 -0
  316. mink/.mypy_cache/3.12/unittest/suite.meta.json +1 -0
  317. mink/.mypy_cache/3.12/warnings.data.json +1 -0
  318. mink/.mypy_cache/3.12/warnings.meta.json +1 -0
  319. mink/.mypy_cache/3.12/zipfile.data.json +1 -0
  320. mink/.mypy_cache/3.12/zipfile.meta.json +1 -0
  321. mink/.mypy_cache/CACHEDIR.TAG +3 -0
  322. mink/__init__.py +75 -0
  323. mink/configuration.py +215 -0
  324. mink/constants.py +34 -0
  325. mink/exceptions.py +98 -0
  326. mink/lie/__init__.py +13 -0
  327. mink/lie/base.py +156 -0
  328. mink/lie/se3.py +249 -0
  329. mink/lie/so3.py +224 -0
  330. mink/lie/tests/__init__.py +0 -0
  331. mink/lie/tests/test_axioms.py +51 -0
  332. mink/lie/tests/test_operations.py +77 -0
  333. mink/lie/tests/utils.py +20 -0
  334. mink/lie/utils.py +29 -0
  335. mink/limits/__init__.py +16 -0
  336. mink/limits/collision_avoidance_limit.py +274 -0
  337. mink/limits/configuration_limit.py +126 -0
  338. mink/limits/exceptions.py +7 -0
  339. mink/limits/limit.py +41 -0
  340. mink/limits/velocity_limit.py +92 -0
  341. mink/py.typed +0 -0
  342. mink/solve_ik.py +105 -0
  343. mink/tasks/__init__.py +26 -0
  344. mink/tasks/com_task.py +82 -0
  345. mink/tasks/exceptions.py +27 -0
  346. mink/tasks/frame_task.py +114 -0
  347. mink/tasks/posture_task.py +103 -0
  348. mink/tasks/task.py +105 -0
  349. mink/utils.py +128 -0
  350. mink-0.0.1.dist-info/METADATA +71 -0
  351. mink-0.0.1.dist-info/RECORD +352 -0
  352. mink-0.0.1.dist-info/WHEEL +4 -0
@@ -0,0 +1,274 @@
1
+ """Collision avoidance limit.
2
+
3
+ Derivation
4
+ ==========
5
+
6
+ p1, p2: closest points between g1 and g2
7
+ d: distance between g1 and g2 (d = ||p1 - p2||)
8
+ n: normal vector from g1 to g2 (n = (p2 - p1) / ||p2 - p1||)
9
+
10
+ The relative velocity constraint between g1 and g2 is given by:
11
+
12
+ n^T [J2(p2) - J1(p1)] dq <= -k * (d - d_min) / dt
13
+ V_n <= -k * (d - d_min)
14
+
15
+ where [J2(p2) - J1(p1)] dq denotes the relative velocity between g1 and g2, and
16
+ n^T [J2(p2) - J1(p1)] dq projects this velocity onto the direction connecting the
17
+ closest points p1 and p2.
18
+
19
+ We have three cases for the distance d:
20
+
21
+ 1. V_n <= R_b if dist_c < dist_m
22
+ 2. V_n <= -k * (dist_c - dist_m) / dt + R_b if dist_m <= d <= dist_d
23
+ 3. V_n <= inf otherwise
24
+
25
+ where:
26
+ - dist_c: current normal distance between g1 and g2
27
+ - dist_m: minimum allowed distance between g1 and g2
28
+ - dist_d: collision detection distance
29
+ """
30
+
31
+ import itertools
32
+ from dataclasses import dataclass
33
+ from typing import List, Sequence, Union
34
+
35
+ import mujoco
36
+ import numpy as np
37
+
38
+ from ..configuration import Configuration
39
+ from .limit import Constraint, Limit
40
+
41
+ # Type aliases.
42
+ Geom = Union[int, str]
43
+ GeomSequence = Sequence[Geom]
44
+ CollisionPair = tuple[GeomSequence, GeomSequence]
45
+ CollisionPairs = Sequence[CollisionPair]
46
+
47
+
48
+ @dataclass(frozen=True)
49
+ class Contact:
50
+ dist: float
51
+ fromto: np.ndarray
52
+ geom1: int
53
+ geom2: int
54
+ distmax: float
55
+
56
+ @property
57
+ def normal(self) -> np.ndarray:
58
+ normal = self.fromto[3:] - self.fromto[:3]
59
+ return normal / (np.linalg.norm(normal) + 1e-9)
60
+
61
+ @property
62
+ def inactive(self) -> bool:
63
+ return self.dist == self.distmax and not self.fromto.any()
64
+
65
+
66
+ def _is_welded_together(model: mujoco.MjModel, geom_id1: int, geom_id2: int) -> bool:
67
+ """Returns true if the geoms are part of the same body, or if their bodies are
68
+ welded together."""
69
+ body1 = model.geom_bodyid[geom_id1]
70
+ body2 = model.geom_bodyid[geom_id2]
71
+ weld1 = model.body_weldid[body1]
72
+ weld2 = model.body_weldid[body2]
73
+ return weld1 == weld2
74
+
75
+
76
+ def _are_geom_bodies_parent_child(
77
+ model: mujoco.MjModel, geom_id1: int, geom_id2: int
78
+ ) -> bool:
79
+ """Returns true if the geom bodies have a parent-child relationship."""
80
+ body_id1 = model.geom_bodyid[geom_id1]
81
+ body_id2 = model.geom_bodyid[geom_id2]
82
+
83
+ # body_weldid is the ID of the body's weld.
84
+ body_weldid1 = model.body_weldid[body_id1]
85
+ body_weldid2 = model.body_weldid[body_id2]
86
+
87
+ # weld_parent_id is the ID of the parent of the body's weld.
88
+ weld_parent_id1 = model.body_parentid[body_weldid1]
89
+ weld_parent_id2 = model.body_parentid[body_weldid2]
90
+
91
+ # weld_parent_weldid is the weld ID of the parent of the body's weld.
92
+ weld_parent_weldid1 = model.body_weldid[weld_parent_id1]
93
+ weld_parent_weldid2 = model.body_weldid[weld_parent_id2]
94
+
95
+ cond1 = body_weldid1 == weld_parent_weldid2
96
+ cond2 = body_weldid2 == weld_parent_weldid1
97
+ return cond1 or cond2
98
+
99
+
100
+ def _is_pass_contype_conaffinity_check(
101
+ model: mujoco.MjModel, geom_id1: int, geom_id2: int
102
+ ) -> bool:
103
+ """Returns true if the geoms pass the contype/conaffinity check."""
104
+ cond1 = bool(model.geom_contype[geom_id1] & model.geom_conaffinity[geom_id2])
105
+ cond2 = bool(model.geom_contype[geom_id2] & model.geom_conaffinity[geom_id1])
106
+ return cond1 or cond2
107
+
108
+
109
+ class CollisionAvoidanceLimit(Limit):
110
+ """Normal velocity limit between geom pairs."""
111
+
112
+ def __init__(
113
+ self,
114
+ model: mujoco.MjModel,
115
+ geom_pairs: CollisionPairs,
116
+ gain: float = 0.85,
117
+ minimum_distance_from_collisions: float = 0.005,
118
+ collision_detection_distance: float = 0.01,
119
+ bound_relaxation: float = 0.0,
120
+ ):
121
+ """Initialize collision avoidance limit.
122
+
123
+ Args:
124
+ model: MuJoCo model.
125
+ geom_pairs: Set of collision pairs in which to perform active collision
126
+ avoidance. A collision pair is defined as a pair of geom groups. A geom
127
+ group is a set of geom names. For each collision pair, the mapper will
128
+ attempt to compute joint velocities that avoid collisions between every
129
+ geom in the first geom group with every geom in the second geom group.
130
+ Self collision is achieved by adding a collision pair with the same
131
+ geom group in both pair fields.
132
+ gain: Gain factor in (0, 1] that determines how fast the geoms are
133
+ allowed to move towards each other at each iteration. Smaller values
134
+ are safer but may make the geoms move slower towards each other.
135
+ minimum_distance_from_collisions: The minimum distance to leave between
136
+ any two geoms. A negative distance allows the geoms to penetrate by
137
+ the specified amount.
138
+ collision_detection_distance: The distance between two geoms at which the
139
+ active collision avoidance limit will be active. A large value will
140
+ cause collisions to be detected early, but may incur high computational
141
+ cost. A negative value will cause the geoms to be detected only after
142
+ they penetrate by the specified amount.
143
+ bound_relaxation: An offset on the upper bound of each collision avoidance
144
+ constraint to tighten or relax
145
+ """
146
+ self.model = model
147
+ self.gain = gain
148
+ self.minimum_distance_from_collisions = minimum_distance_from_collisions
149
+ self.collision_detection_distance = collision_detection_distance
150
+ self.bound_relaxation = bound_relaxation
151
+ self.geom_id_pairs = self._construct_geom_id_pairs(geom_pairs)
152
+ self.max_num_contacts = len(self.geom_id_pairs)
153
+
154
+ def compute_qp_inequalities(
155
+ self,
156
+ configuration: Configuration,
157
+ dt: float,
158
+ ) -> Constraint:
159
+ upper_bound = np.full((self.max_num_contacts,), np.inf)
160
+ coefficient_matrix = np.zeros((self.max_num_contacts, self.model.nv))
161
+ for idx, (geom1_id, geom2_id) in enumerate(self.geom_id_pairs):
162
+ contact = self._compute_contact_with_minimum_distance(
163
+ configuration.data, geom1_id, geom2_id
164
+ )
165
+ if contact.inactive:
166
+ continue
167
+ hi_bound_dist = contact.dist
168
+ if hi_bound_dist > self.minimum_distance_from_collisions:
169
+ dist = hi_bound_dist - self.minimum_distance_from_collisions
170
+ upper_bound[idx] = (self.gain * dist / dt) + self.bound_relaxation
171
+ else:
172
+ upper_bound[idx] = self.bound_relaxation
173
+ jac = self._compute_contact_normal_jacobian(configuration.data, contact)
174
+ coefficient_matrix[idx] = -jac
175
+ return Constraint(G=coefficient_matrix, h=upper_bound)
176
+
177
+ # Private methods.
178
+
179
+ def _compute_contact_with_minimum_distance(
180
+ self, data: mujoco.MjData, geom1_id: int, geom2_id: int
181
+ ) -> Contact:
182
+ """Returns the smallest signed distance between a geom pair."""
183
+ fromto = np.empty(6)
184
+ dist = mujoco.mj_geomDistance(
185
+ self.model,
186
+ data,
187
+ geom1_id,
188
+ geom2_id,
189
+ self.collision_detection_distance,
190
+ fromto,
191
+ )
192
+ return Contact(
193
+ dist, fromto, geom1_id, geom2_id, self.collision_detection_distance
194
+ )
195
+
196
+ def _compute_contact_normal_jacobian(
197
+ self, data: mujoco.MjData, contact: Contact
198
+ ) -> np.ndarray:
199
+ """Computes the Jacobian mapping joint velocities to the normal component of
200
+ the relative Cartesian linear velocity between the geom pair.
201
+
202
+ The Jacobian-velocity relationship is given as:
203
+
204
+ J dq = n^T (v_2 - v_1)
205
+
206
+ where:
207
+ * J is the computed Jacobian.
208
+ * dq is the joint velocity vector.
209
+ * n^T is the transpose of the normal pointing from contact.geom1 to
210
+ contact.geom2.
211
+ * v_1, v_2 are the linear components of the Cartesian velocity of the two
212
+ closest points in contact.geom1 and contact.geom2.
213
+
214
+ Note: n^T (v_2 - v_1) is a scalar that is positive if the geoms are moving away
215
+ from each other, and negative if they are moving towards each other.
216
+ """
217
+ geom1_body = self.model.geom_bodyid[contact.geom1]
218
+ geom2_body = self.model.geom_bodyid[contact.geom2]
219
+ geom1_contact_pos = contact.fromto[:3]
220
+ geom2_contact_pos = contact.fromto[3:]
221
+ jac2 = np.empty((3, self.model.nv))
222
+ mujoco.mj_jac(self.model, data, jac2, None, geom2_contact_pos, geom2_body)
223
+ jac1 = np.empty((3, self.model.nv))
224
+ mujoco.mj_jac(self.model, data, jac1, None, geom1_contact_pos, geom1_body)
225
+ return contact.normal @ (jac2 - jac1)
226
+
227
+ def _homogenize_geom_id_list(self, geom_list: GeomSequence) -> List[int]:
228
+ """Take a heterogeneous list of geoms (specified via ID or name) and return
229
+ a homogenous list of IDs (int)."""
230
+ list_of_int: list[int] = []
231
+ for g in geom_list:
232
+ if isinstance(g, int):
233
+ list_of_int.append(g)
234
+ else:
235
+ assert isinstance(g, str)
236
+ list_of_int.append(self.model.geom(g).id)
237
+ return list_of_int
238
+
239
+ def _collision_pairs_to_geom_id_pairs(self, collision_pairs: CollisionPairs):
240
+ geom_id_pairs = []
241
+ for collision_pair in collision_pairs:
242
+ id_pair_A = self._homogenize_geom_id_list(collision_pair[0])
243
+ id_pair_B = self._homogenize_geom_id_list(collision_pair[1])
244
+ id_pair_A = list(set(id_pair_A))
245
+ id_pair_B = list(set(id_pair_B))
246
+ geom_id_pairs.append((id_pair_A, id_pair_B))
247
+ return geom_id_pairs
248
+
249
+ def _construct_geom_id_pairs(self, geom_pairs):
250
+ """Returns a set of geom ID pairs for all possible geom-geom collisions.
251
+
252
+ The contacts are added based on the following heuristics:
253
+ 1) Geoms that are part of the same body or weld are not included.
254
+ 2) Geoms where the body of one geom is a parent of the body of the other
255
+ geom are not included.
256
+ 3) Geoms that fail the contype-conaffinity check are ignored.
257
+
258
+ Note:
259
+ 1) If two bodies are kinematically welded together (no joints between them)
260
+ they are considered to be the same body within this function.
261
+ """
262
+ geom_id_pairs = []
263
+ for id_pair in self._collision_pairs_to_geom_id_pairs(geom_pairs):
264
+ for geom_a, geom_b in itertools.product(*id_pair):
265
+ weld_body_cond = not _is_welded_together(self.model, geom_a, geom_b)
266
+ parent_child_cond = not _are_geom_bodies_parent_child(
267
+ self.model, geom_a, geom_b
268
+ )
269
+ contype_conaffinity_cond = _is_pass_contype_conaffinity_check(
270
+ self.model, geom_a, geom_b
271
+ )
272
+ if weld_body_cond and parent_child_cond and contype_conaffinity_cond:
273
+ geom_id_pairs.append((min(geom_a, geom_b), max(geom_a, geom_b)))
274
+ return geom_id_pairs
@@ -0,0 +1,126 @@
1
+ """Limit on joint positions.
2
+
3
+ Derivation
4
+ ==========
5
+
6
+ Using a first order Taylor expansion on the configuration, we can write the limit as:
7
+
8
+ q_min <= q + v * dt <= q_max
9
+ q_min <= q + dq <= q_max
10
+ q_min - q <= dq <= q_max - q
11
+
12
+ Rewriting as G dq <= h:
13
+
14
+ +I * dq <= q_max - q
15
+ -I * dq <= q - q_min
16
+
17
+ Stacking them together, we get:
18
+
19
+ G = [+I, -I]
20
+ h = [q_max - q, q - q_min]
21
+ """
22
+
23
+ import mujoco
24
+ import numpy as np
25
+
26
+ from ..configuration import Configuration
27
+ from ..constants import qpos_width
28
+ from .exceptions import LimitDefinitionError
29
+ from .limit import Constraint, Limit
30
+
31
+
32
+ class ConfigurationLimit(Limit):
33
+ """Limit for joint positions in a model.
34
+
35
+ Floating base joints (joint type="free") are ignored.
36
+
37
+ Attributes:
38
+ indices: Tangent indices corresponding to configuration-limited joints.
39
+ projection_matrix: Projection from tangent space to subspace with
40
+ configuration-limited joints.
41
+ lower: Lower configuration limit.
42
+ upper: Upper configuration limit.
43
+ """
44
+
45
+ def __init__(
46
+ self,
47
+ model: mujoco.MjModel,
48
+ gain: float = 0.95,
49
+ min_distance_from_limits: float = 0.0,
50
+ ):
51
+ """Initialize configuration limits.
52
+
53
+ Args:
54
+ model: MuJoCo model.
55
+ gain: Gain factor in (0, 1] that determines how fast each joint is
56
+ allowed to move towards the joint limits at each timestep. Values lower
57
+ ttan 1 are safer but may make the joints move slowly.
58
+ min_distance_from_limits: Offset in meters (slide joints) or radians
59
+ (hinge joints) to be added to the limits. Positive values decrease the
60
+ range of motion, negative values increase it (i.e. negative values
61
+ allow penetration).
62
+ """
63
+ if not 0.0 < gain <= 1.0:
64
+ raise LimitDefinitionError(
65
+ f"{self.__class__.__name__} gain must be in the range (0, 1]"
66
+ )
67
+
68
+ index_list: list[int] = []
69
+ lower = np.full(model.nq, -np.inf)
70
+ upper = np.full(model.nq, np.inf)
71
+ for jnt in range(model.njnt):
72
+ jnt_type = model.jnt_type[jnt]
73
+ qpos_dim = qpos_width(jnt_type)
74
+ jnt_range = model.jnt_range[jnt]
75
+ padr = model.jnt_qposadr[jnt]
76
+ if jnt_type == mujoco.mjtJoint.mjJNT_FREE or not model.jnt_limited[jnt]:
77
+ continue
78
+ lower[padr : padr + qpos_dim] = jnt_range[0] + min_distance_from_limits
79
+ upper[padr : padr + qpos_dim] = jnt_range[1] - min_distance_from_limits
80
+ index_list.append(jnt)
81
+
82
+ self.indices = np.array(index_list)
83
+ self.indices.setflags(write=False)
84
+
85
+ dim = len(self.indices)
86
+ self.projection_matrix = np.eye(model.nv)[self.indices] if dim > 0 else None
87
+
88
+ self.lower = lower
89
+ self.upper = upper
90
+ self.model = model
91
+ self.gain = gain
92
+
93
+ def compute_qp_inequalities(
94
+ self,
95
+ configuration: Configuration,
96
+ dt: float,
97
+ ) -> Constraint:
98
+ del dt # Unused.
99
+
100
+ # Upper.
101
+ delta_q_max = np.zeros(self.model.nv)
102
+ mujoco.mj_differentiatePos(
103
+ m=self.model,
104
+ qvel=delta_q_max,
105
+ dt=1.0,
106
+ qpos1=configuration.q,
107
+ qpos2=self.upper,
108
+ )
109
+
110
+ # Lower.
111
+ delta_q_min = np.zeros(self.model.nv)
112
+ mujoco.mj_differentiatePos(
113
+ m=self.model,
114
+ qvel=delta_q_min,
115
+ dt=1.0,
116
+ # NOTE: mujoco.mj_differentiatePos does `qpos2 - qpos1` so notice the order
117
+ # swap here compared to above.
118
+ qpos1=self.lower,
119
+ qpos2=configuration.q,
120
+ )
121
+
122
+ p_min = self.gain * delta_q_min[self.indices]
123
+ p_max = self.gain * delta_q_max[self.indices]
124
+ G = np.vstack([self.projection_matrix, -self.projection_matrix])
125
+ h = np.hstack([p_max, p_min])
126
+ return Constraint(G=G, h=h)
@@ -0,0 +1,7 @@
1
+ """Exceptions raised by limits."""
2
+
3
+ from ..exceptions import MinkError
4
+
5
+
6
+ class LimitDefinitionError(MinkError):
7
+ """Exception raised when a limit definition is ill-formed."""
mink/limits/limit.py ADDED
@@ -0,0 +1,41 @@
1
+ import abc
2
+ from typing import NamedTuple, Optional
3
+
4
+ import numpy as np
5
+
6
+ from ..configuration import Configuration
7
+
8
+
9
+ class Constraint(NamedTuple):
10
+ """Linear inequalities in the form G(q) dq <= h(q).
11
+
12
+ The limit is considered inactive when G or h are None.
13
+ """
14
+
15
+ G: Optional[np.ndarray] = None # (nv, nv)
16
+ h: Optional[np.ndarray] = None # (nv,)
17
+
18
+ @property
19
+ def inactive(self) -> bool:
20
+ return self.G is None or self.h is None
21
+
22
+
23
+ class Limit(abc.ABC):
24
+ """Abstract base class for kinematic limits."""
25
+
26
+ @abc.abstractmethod
27
+ def compute_qp_inequalities(
28
+ self,
29
+ configuration: Configuration,
30
+ dt: float,
31
+ ) -> Constraint:
32
+ """Compute limit as linearized QP inequalities.
33
+
34
+ Args:
35
+ configuration: Current configuration.
36
+ dt: Integration time step in [s].
37
+
38
+ Returns:
39
+ Pair (G, h) representing the inequality constraint.
40
+ """
41
+ raise NotImplementedError
@@ -0,0 +1,92 @@
1
+ """Limit on joint velocities.
2
+
3
+ Derivation
4
+ ==========
5
+
6
+ Given maximum joint velocity magnitudes v_max, we can express joint velocity limits as:
7
+
8
+ -v_max <= v <= v_max
9
+ -v_max <= dq / dt <= v_max
10
+ -v_max * dt <= dq <= v_max * dt
11
+
12
+ Rewriting as G dq <= h:
13
+
14
+ +I * dq <= v_max * dt
15
+ -I * dq <= v_max * dt
16
+
17
+ Stacking them together, we get:
18
+
19
+ G = [+I, -I]
20
+ h = [v_max * dt, v_max * dt]
21
+ """
22
+
23
+ from typing import Mapping
24
+
25
+ import mujoco
26
+ import numpy as np
27
+ import numpy.typing as npt
28
+
29
+ from ..configuration import Configuration
30
+ from ..constants import dof_width
31
+ from .exceptions import LimitDefinitionError
32
+ from .limit import Constraint, Limit
33
+
34
+
35
+ class VelocityLimit(Limit):
36
+ """Limit for joint velocities in a model.
37
+
38
+ Floating base joints are ignored.
39
+
40
+ Attributes:
41
+ indices: Tangent indices corresponding to velocity-limited joints.
42
+ limit: Maximum allowed velocity magnitude for velocity-limited joints.
43
+ projection_matrix: Projection from tangent space to subspace with
44
+ velocity-limited joints.
45
+ """
46
+
47
+ def __init__(
48
+ self,
49
+ model: mujoco.MjModel,
50
+ velocities: Mapping[str, npt.ArrayLike] = {},
51
+ ):
52
+ """Initialize velocity limits.
53
+
54
+ Args:
55
+ velocities: Dictionary mapping joint name to maximum allowed magnitude in
56
+ [m]/[s] for slide joints and [rad]/[s] for hinge joints.
57
+ """
58
+ limit_list: list[float] = []
59
+ index_list: list[int] = []
60
+ for joint_name, max_vel in velocities.items():
61
+ jid = model.joint(joint_name).id
62
+ jnt_type = model.jnt_type[jid]
63
+ jnt_dim = dof_width(jnt_type)
64
+ jnt_id = model.jnt_dofadr[jid]
65
+ if jnt_type == mujoco.mjtJoint.mjJNT_FREE:
66
+ raise LimitDefinitionError(f"Free joint {joint_name} is not supported")
67
+ max_vel = np.atleast_1d(max_vel)
68
+ if max_vel.shape != (jnt_dim,):
69
+ raise LimitDefinitionError(
70
+ f"Joint {joint_name} must have a limit of shape ({jnt_dim},). "
71
+ f"Got: {max_vel.shape}"
72
+ )
73
+ index_list.extend(range(jnt_id, jnt_id + jnt_dim))
74
+ limit_list.extend(max_vel.tolist())
75
+
76
+ self.indices = np.array(index_list)
77
+ self.indices.setflags(write=False)
78
+ self.limit = np.array(limit_list)
79
+ self.limit.setflags(write=False)
80
+
81
+ dim = len(self.indices)
82
+ self.projection_matrix = np.eye(model.nv)[self.indices] if dim > 0 else None
83
+
84
+ def compute_qp_inequalities(
85
+ self, configuration: Configuration, dt: float
86
+ ) -> Constraint:
87
+ del configuration # Unused.
88
+ if self.projection_matrix is None:
89
+ return Constraint()
90
+ G = np.vstack([self.projection_matrix, -self.projection_matrix])
91
+ h = np.hstack([dt * self.limit, dt * self.limit])
92
+ return Constraint(G=G, h=h)
mink/py.typed ADDED
File without changes
mink/solve_ik.py ADDED
@@ -0,0 +1,105 @@
1
+ """Build and solve the inverse kinematics problem."""
2
+
3
+ from typing import Optional, Sequence
4
+
5
+ import numpy as np
6
+ import qpsolvers
7
+
8
+ from .configuration import Configuration
9
+ from .limits import ConfigurationLimit, Limit
10
+ from .tasks import Objective, Task
11
+
12
+
13
+ def _compute_qp_objective(
14
+ configuration: Configuration, tasks: Sequence[Task], damping: float
15
+ ) -> Objective:
16
+ H = np.eye(configuration.model.nv) * damping
17
+ c = np.zeros(configuration.model.nv)
18
+ for task in tasks:
19
+ H_task, c_task = task.compute_qp_objective(configuration)
20
+ H += H_task
21
+ c += c_task
22
+ return Objective(H, c)
23
+
24
+
25
+ def _compute_qp_inequalities(
26
+ configuration: Configuration, limits: Optional[Sequence[Limit]], dt: float
27
+ ) -> tuple[Optional[np.ndarray], Optional[np.ndarray]]:
28
+ if limits is None:
29
+ limits = [ConfigurationLimit(configuration.model)]
30
+ G_list = []
31
+ h_list = []
32
+ for limit in limits:
33
+ inequality = limit.compute_qp_inequalities(configuration, dt)
34
+ if not inequality.inactive:
35
+ assert inequality.G is not None and inequality.h is not None # mypy.
36
+ G_list.append(inequality.G)
37
+ h_list.append(inequality.h)
38
+ if not G_list:
39
+ return None, None
40
+ return np.vstack(G_list), np.hstack(h_list)
41
+
42
+
43
+ def build_ik(
44
+ configuration: Configuration,
45
+ tasks: Sequence[Task],
46
+ dt: float,
47
+ damping: float = 1e-12,
48
+ limits: Optional[Sequence[Limit]] = None,
49
+ ) -> qpsolvers.Problem:
50
+ """Build quadratic program from current configuration and tasks.
51
+
52
+ Args:
53
+ configuration: Robot configuration.
54
+ tasks: List of kinematic tasks.
55
+ dt: Integration timestep in [s].
56
+ damping: Levenberg-Marquardt damping.
57
+ limits: List of limits to enforce. Set to empty list to disable. If None,
58
+ defaults to a configuration limit.
59
+
60
+ Returns:
61
+ Quadratic program of the inverse kinematics problem.
62
+ """
63
+ P, q = _compute_qp_objective(configuration, tasks, damping)
64
+ G, h = _compute_qp_inequalities(configuration, limits, dt)
65
+ return qpsolvers.Problem(P, q, G, h)
66
+
67
+
68
+ def solve_ik(
69
+ configuration: Configuration,
70
+ tasks: Sequence[Task],
71
+ dt: float,
72
+ solver: str,
73
+ damping: float = 1e-12,
74
+ safety_break: bool = False,
75
+ limits: Optional[Sequence[Limit]] = None,
76
+ **kwargs,
77
+ ) -> np.ndarray:
78
+ """Solve the differential inverse kinematics problem.
79
+
80
+ Computes a velocity tangent to the current robot configuration. The computed
81
+ velocity satisfies at (weighted) best the set of provided kinematic tasks.
82
+
83
+ Args:
84
+ configuration: Robot configuration.
85
+ tasks: List of kinematic tasks.
86
+ dt: Integration timestep in [s].
87
+ solver: Backend quadratic programming (QP) solver.
88
+ damping: Levenberg-Marquardt damping.
89
+ safety_break: If True, stop execution and raise an exception if
90
+ the current configuration is outside limits. If False, print a
91
+ warning and continue execution.
92
+ limits: List of limits to enforce. Set to empty list to disable. If None,
93
+ defaults to a configuration limit.
94
+ kwargs: Keyword arguments to forward to the backend QP solver.
95
+
96
+ Returns:
97
+ Velocity `v` in tangent space.
98
+ """
99
+ configuration.check_limits(safety_break=safety_break)
100
+ problem = build_ik(configuration, tasks, dt, damping, limits)
101
+ result = qpsolvers.solve_problem(problem, solver=solver, **kwargs)
102
+ dq = result.x
103
+ assert dq is not None
104
+ v: np.ndarray = dq / dt
105
+ return v
mink/tasks/__init__.py ADDED
@@ -0,0 +1,26 @@
1
+ """Kinematic tasks."""
2
+
3
+ from .com_task import ComTask
4
+ from .exceptions import (
5
+ InvalidDamping,
6
+ InvalidGain,
7
+ InvalidTarget,
8
+ TargetNotSet,
9
+ TaskDefinitionError,
10
+ )
11
+ from .frame_task import FrameTask
12
+ from .posture_task import PostureTask
13
+ from .task import Objective, Task
14
+
15
+ __all__ = (
16
+ "ComTask",
17
+ "FrameTask",
18
+ "Objective",
19
+ "PostureTask",
20
+ "Task",
21
+ "TargetNotSet",
22
+ "InvalidTarget",
23
+ "TaskDefinitionError",
24
+ "InvalidGain",
25
+ "InvalidDamping",
26
+ )