scikit-robot 0.4.0__tar.gz → 0.4.2__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 (221) hide show
  1. {scikit_robot-0.4.0/scikit_robot.egg-info → scikit_robot-0.4.2}/PKG-INFO +1 -1
  2. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/pyproject.toml +1 -1
  3. {scikit_robot-0.4.0 → scikit_robot-0.4.2/scikit_robot.egg-info}/PKG-INFO +1 -1
  4. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/scikit_robot.egg-info/SOURCES.txt +3 -0
  5. scikit_robot-0.4.2/skrobot/backend/math_utils.py +78 -0
  6. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/coordinates/base.py +33 -17
  7. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/export/usd.py +84 -8
  8. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/interfaces/ros2/base.py +118 -6
  9. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/kinematics/__init__.py +16 -0
  10. scikit_robot-0.4.2/skrobot/kinematics/_base_placement_jax.py +268 -0
  11. scikit_robot-0.4.2/skrobot/kinematics/base_placement.py +1340 -0
  12. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/kinematics/differentiable.py +63 -60
  13. scikit_robot-0.4.2/skrobot/kinematics/inverse_reachability_map.py +422 -0
  14. scikit_robot-0.4.0/skrobot/backend/math_utils.py +0 -74
  15. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/LICENSE +0 -0
  16. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/MANIFEST.in +0 -0
  17. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/README.md +0 -0
  18. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/scikit_robot.egg-info/dependency_links.txt +0 -0
  19. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/scikit_robot.egg-info/entry_points.txt +0 -0
  20. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/scikit_robot.egg-info/not-zip-safe +0 -0
  21. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/scikit_robot.egg-info/requires.txt +0 -0
  22. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/scikit_robot.egg-info/top_level.txt +0 -0
  23. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/setup.cfg +0 -0
  24. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/__init__.py +0 -0
  25. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/_lazy_imports.py +0 -0
  26. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/apps/__init__.py +0 -0
  27. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/apps/canonicalize_urdf.py +0 -0
  28. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/apps/change_urdf_root.py +0 -0
  29. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/apps/cli.py +0 -0
  30. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/apps/convert_urdf_mesh.py +0 -0
  31. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/apps/convert_urdf_to_mjcf.py +0 -0
  32. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/apps/convert_urdf_to_primitives.py +0 -0
  33. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/apps/convert_wheel_collision.py +0 -0
  34. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/apps/extract_sub_urdf.py +0 -0
  35. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/apps/generate_robot_class.py +0 -0
  36. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/apps/modularize_urdf.py +0 -0
  37. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/apps/scale_urdf.py +0 -0
  38. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/apps/transform_urdf.py +0 -0
  39. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/apps/urdf_hash.py +0 -0
  40. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/apps/urdf_tree.py +0 -0
  41. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/apps/visualize_mesh.py +0 -0
  42. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/apps/visualize_urdf.py +0 -0
  43. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/assembly/__init__.py +0 -0
  44. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/assembly/module_assembly.py +0 -0
  45. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/assembly/module_registry.py +0 -0
  46. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/backend/__init__.py +0 -0
  47. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/backend/jax_backend.py +0 -0
  48. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/backend/numpy_backend.py +0 -0
  49. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/backend/registry.py +0 -0
  50. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/collision/__init__.py +0 -0
  51. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/collision/distance.py +0 -0
  52. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/collision/geometry.py +0 -0
  53. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/collision/robot_collision.py +0 -0
  54. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/collision/self_collision.py +0 -0
  55. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/coordinates/__init__.py +0 -0
  56. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/coordinates/geo.py +0 -0
  57. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/coordinates/math.py +0 -0
  58. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/data/__init__.py +0 -0
  59. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/data/kuka_description/kuka.urdf +0 -0
  60. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/data/kuka_description/meshes/finger_base_left.stl +0 -0
  61. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/data/kuka_description/meshes/finger_base_right.stl +0 -0
  62. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/data/kuka_description/meshes/finger_tip_left.stl +0 -0
  63. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/data/kuka_description/meshes/finger_tip_right.stl +0 -0
  64. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/data/kuka_description/meshes/link_0.mtl +0 -0
  65. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/data/kuka_description/meshes/link_0.obj +0 -0
  66. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/data/kuka_description/meshes/link_0.stl +0 -0
  67. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/data/kuka_description/meshes/link_1.mtl +0 -0
  68. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/data/kuka_description/meshes/link_1.obj +0 -0
  69. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/data/kuka_description/meshes/link_1.stl +0 -0
  70. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/data/kuka_description/meshes/link_2.mtl +0 -0
  71. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/data/kuka_description/meshes/link_2.obj +0 -0
  72. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/data/kuka_description/meshes/link_2.stl +0 -0
  73. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/data/kuka_description/meshes/link_3.mtl +0 -0
  74. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/data/kuka_description/meshes/link_3.obj +0 -0
  75. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/data/kuka_description/meshes/link_3.stl +0 -0
  76. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/data/kuka_description/meshes/link_4.mtl +0 -0
  77. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/data/kuka_description/meshes/link_4.obj +0 -0
  78. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/data/kuka_description/meshes/link_4.stl +0 -0
  79. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/data/kuka_description/meshes/link_5.mtl +0 -0
  80. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/data/kuka_description/meshes/link_5.obj +0 -0
  81. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/data/kuka_description/meshes/link_5.stl +0 -0
  82. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/data/kuka_description/meshes/link_6.mtl +0 -0
  83. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/data/kuka_description/meshes/link_6.obj +0 -0
  84. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/data/kuka_description/meshes/link_6.stl +0 -0
  85. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/data/kuka_description/meshes/link_7.mtl +0 -0
  86. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/data/kuka_description/meshes/link_7.obj +0 -0
  87. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/data/kuka_description/meshes/link_7.stl +0 -0
  88. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/data/robot_descriptions/urdf/r8_6.urdf +0 -0
  89. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/data/ros_config_templates/CMakeLists.txt.ros2.template +0 -0
  90. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/data/ros_config_templates/gazebo.launch.py.template +0 -0
  91. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/data/ros_config_templates/gazebo_moveit.launch.py.template +0 -0
  92. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/data/ros_config_templates/isaac_fjt_server.py.template +0 -0
  93. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/data/ros_config_templates/moveit.rviz.template +0 -0
  94. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/data/ros_config_templates/package.xml.ros2.template +0 -0
  95. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/data/ros_config_templates/ros2_control.xacro.joint.template +0 -0
  96. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/data/ros_config_templates/ros2_control.xacro.template +0 -0
  97. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/data/ros_config_templates/setup_assistant.template +0 -0
  98. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/dynamics/__init__.py +0 -0
  99. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/dynamics/differentiable.py +0 -0
  100. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/dynamics/gravity.py +0 -0
  101. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/export/__init__.py +0 -0
  102. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/export/contact_links.py +0 -0
  103. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/export/isaac/__init__.py +0 -0
  104. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/export/isaac/fjt_server.py +0 -0
  105. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/export/task.py +0 -0
  106. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/interfaces/__init__.py +0 -0
  107. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/interfaces/_pybullet.py +0 -0
  108. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/interfaces/ros/__init__.py +0 -0
  109. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/interfaces/ros/base.py +0 -0
  110. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/interfaces/ros/move_base.py +0 -0
  111. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/interfaces/ros/nextage.py +0 -0
  112. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/interfaces/ros/panda.py +0 -0
  113. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/interfaces/ros/pr2.py +0 -0
  114. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/interfaces/ros/tf_utils.py +0 -0
  115. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/interfaces/ros/transform_listener.py +0 -0
  116. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/interfaces/ros2/__init__.py +0 -0
  117. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/interfaces/ros2/gripper.py +0 -0
  118. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/interfaces/ros2/panda.py +0 -0
  119. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/kinematics/loop_closure.py +0 -0
  120. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/kinematics/reachability_map.py +0 -0
  121. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/model/__init__.py +0 -0
  122. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/model/joint.py +0 -0
  123. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/model/joint_limit_table.py +0 -0
  124. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/model/link.py +0 -0
  125. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/model/primitives.py +0 -0
  126. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/model/robot_model.py +0 -0
  127. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/model/skeleton.py +0 -0
  128. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/models/__init__.py +0 -0
  129. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/models/aero.py +0 -0
  130. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/models/differential_wrist_sample.py +0 -0
  131. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/models/fetch.py +0 -0
  132. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/models/g1.py +0 -0
  133. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/models/griphis.py +0 -0
  134. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/models/hydrus.py +0 -0
  135. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/models/jaxon_jvrc.py +0 -0
  136. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/models/jedy.py +0 -0
  137. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/models/kuka.py +0 -0
  138. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/models/nextage.py +0 -0
  139. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/models/panda.py +0 -0
  140. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/models/pr2.py +0 -0
  141. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/models/r8_6.py +0 -0
  142. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/models/tycoon.py +0 -0
  143. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/models/urdf.py +0 -0
  144. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/planner/__init__.py +0 -0
  145. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/planner/collision_checker.py +0 -0
  146. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/planner/inverse_kinematics_optimization.py +0 -0
  147. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/planner/sqp_based.py +0 -0
  148. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/planner/swept_sphere.py +0 -0
  149. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/planner/trajectory_optimization/__init__.py +0 -0
  150. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/planner/trajectory_optimization/collision.py +0 -0
  151. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/planner/trajectory_optimization/fk_utils.py +0 -0
  152. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/planner/trajectory_optimization/gridsdf_collision.py +0 -0
  153. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/planner/trajectory_optimization/problem.py +0 -0
  154. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/planner/trajectory_optimization/residuals.py +0 -0
  155. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/planner/trajectory_optimization/solvers/__init__.py +0 -0
  156. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/planner/trajectory_optimization/solvers/augmented_lagrangian.py +0 -0
  157. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/planner/trajectory_optimization/solvers/base.py +0 -0
  158. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/planner/trajectory_optimization/solvers/gradient_descent.py +0 -0
  159. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/planner/trajectory_optimization/solvers/jaxls_solver.py +0 -0
  160. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/planner/trajectory_optimization/solvers/scipy_solver.py +0 -0
  161. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/planner/trajectory_optimization/solvers/solver_utils.py +0 -0
  162. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/planner/trajectory_optimization/trajectory.py +0 -0
  163. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/planner/trajectory_optimization/world_surface_collision.py +0 -0
  164. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/planner/utils.py +0 -0
  165. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/pycompat.py +0 -0
  166. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/sdf/__init__.py +0 -0
  167. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/sdf/signed_distance_function.py +0 -0
  168. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/urdf/__init__.py +0 -0
  169. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/urdf/aggregate.py +0 -0
  170. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/urdf/canonicalize.py +0 -0
  171. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/urdf/compare.py +0 -0
  172. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/urdf/extract_sub_urdf.py +0 -0
  173. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/urdf/flip_axis.py +0 -0
  174. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/urdf/hash.py +0 -0
  175. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/urdf/link_origins.py +0 -0
  176. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/urdf/llm_grouping.py +0 -0
  177. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/urdf/merge_fixed_links.py +0 -0
  178. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/urdf/modularize_urdf.py +0 -0
  179. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/urdf/primitives_converter.py +0 -0
  180. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/urdf/robot_class_generator.py +0 -0
  181. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/urdf/ros_config/__init__.py +0 -0
  182. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/urdf/ros_config/export.py +0 -0
  183. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/urdf/ros_config/gazebo_generator.py +0 -0
  184. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/urdf/ros_config/moveit_generator.py +0 -0
  185. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/urdf/ros_config/moveit_package.py +0 -0
  186. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/urdf/ros_config/urdf_parser.py +0 -0
  187. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/urdf/ros_package.py +0 -0
  188. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/urdf/ros_package_exporter.py +0 -0
  189. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/urdf/sanitize.py +0 -0
  190. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/urdf/scale_urdf.py +0 -0
  191. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/urdf/structure.py +0 -0
  192. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/urdf/transform_urdf.py +0 -0
  193. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/urdf/wheel_collision_converter.py +0 -0
  194. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/urdf/xml_root_link_changer.py +0 -0
  195. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/utils/__init__.py +0 -0
  196. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/utils/_blender_decimate_core.py +0 -0
  197. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/utils/_blender_remesh_core.py +0 -0
  198. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/utils/archive.py +0 -0
  199. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/utils/blender_mesh.py +0 -0
  200. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/utils/checksum.py +0 -0
  201. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/utils/convex_decomposition.py +0 -0
  202. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/utils/draco.py +0 -0
  203. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/utils/inertia.py +0 -0
  204. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/utils/listify.py +0 -0
  205. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/utils/mesh.py +0 -0
  206. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/utils/mjcf_converter.py +0 -0
  207. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/utils/package.py +0 -0
  208. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/utils/primitive_fitting.py +0 -0
  209. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/utils/urdf.py +0 -0
  210. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/utils/urdf_mesh.py +0 -0
  211. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/utils/video.py +0 -0
  212. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/utils/visualization.py +0 -0
  213. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/viewers/__init__.py +0 -0
  214. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/viewers/_base.py +0 -0
  215. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/viewers/_manipulability_ellipse.py +0 -0
  216. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/viewers/_mitsuba.py +0 -0
  217. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/viewers/_notebook.py +0 -0
  218. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/viewers/_path_utils.py +0 -0
  219. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/viewers/_pyrender.py +0 -0
  220. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/viewers/_trimesh.py +0 -0
  221. {scikit_robot-0.4.0 → scikit_robot-0.4.2}/skrobot/viewers/_viser.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: scikit-robot
3
- Version: 0.4.0
3
+ Version: 0.4.2
4
4
  Summary: A Flexible Framework for Robot Control in Python
5
5
  Author-email: iory <ab.ioryz@gmail.com>
6
6
  License: MIT
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "scikit-robot"
7
- version = "0.4.0"
7
+ version = "0.4.2"
8
8
  description = "A Flexible Framework for Robot Control in Python"
9
9
  readme = "README.md"
10
10
  license = {text = "MIT"}
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: scikit-robot
3
- Version: 0.4.0
3
+ Version: 0.4.2
4
4
  Summary: A Flexible Framework for Robot Control in Python
5
5
  Author-email: iory <ab.ioryz@gmail.com>
6
6
  License: MIT
@@ -110,7 +110,10 @@ skrobot/interfaces/ros2/base.py
110
110
  skrobot/interfaces/ros2/gripper.py
111
111
  skrobot/interfaces/ros2/panda.py
112
112
  skrobot/kinematics/__init__.py
113
+ skrobot/kinematics/_base_placement_jax.py
114
+ skrobot/kinematics/base_placement.py
113
115
  skrobot/kinematics/differentiable.py
116
+ skrobot/kinematics/inverse_reachability_map.py
114
117
  skrobot/kinematics/loop_closure.py
115
118
  skrobot/kinematics/reachability_map.py
116
119
  skrobot/model/__init__.py
@@ -0,0 +1,78 @@
1
+ """Backend-agnostic math utilities for differentiable computation.
2
+
3
+ This module provides common mathematical operations that work with
4
+ any backend (NumPy, JAX) for use in kinematics and dynamics computations.
5
+ """
6
+
7
+ import numpy as np
8
+
9
+
10
+ # _CROSS[i, j, k] = -epsilon_ijk, so _CROSS @ v is the cross-product
11
+ # matrix of v. One matmul builds it for a single vector or a batch; nested
12
+ # stacks would cost several times as much per call on the NumPy FK path.
13
+ _CROSS = np.zeros((3, 3, 3))
14
+ for _i, _j, _k in ((0, 1, 2), (1, 2, 0), (2, 0, 1)):
15
+ _CROSS[_i, _j, _k] = -1.0
16
+ _CROSS[_i, _k, _j] = 1.0
17
+
18
+
19
+ def rodrigues_rotation(backend, axis, angle):
20
+ """Compute rotation matrix from axis-angle using Rodrigues' formula.
21
+
22
+ R = I + sin(θ)K + (1-cos(θ))K²
23
+
24
+ where K is the skew-symmetric matrix of the normalized axis.
25
+
26
+ Parameters
27
+ ----------
28
+ backend : DifferentiableBackend or module
29
+ Backend to use for computation (numpy or jax). The ``numpy`` and
30
+ ``jax.numpy`` modules work as well.
31
+ axis : array, shape (3,) or (..., 3)
32
+ Rotation axis (will be normalized), or a batch of them.
33
+ angle : float or array, shape () or (...)
34
+ Rotation angle in radians, one per axis.
35
+
36
+ Returns
37
+ -------
38
+ rotation : array, shape (3, 3) or (..., 3, 3)
39
+ Rotation matrix, or one per axis.
40
+
41
+ Examples
42
+ --------
43
+ >>> from skrobot.backend import get_backend
44
+ >>> from skrobot.backend.math_utils import rodrigues_rotation
45
+ >>> backend = get_backend('numpy')
46
+ >>> axis = backend.array([0.0, 0.0, 1.0])
47
+ >>> R = rodrigues_rotation(backend, axis, 0.5)
48
+ """
49
+ # Normalize axis
50
+ axis = axis / (backend.sqrt((axis ** 2).sum(axis=-1, keepdims=True))
51
+ + 1e-10)
52
+ K = skew_symmetric(backend, axis)
53
+
54
+ # Rodrigues formula
55
+ sin = backend.sin(angle)[..., None, None]
56
+ cos = backend.cos(angle)[..., None, None]
57
+ return backend.eye(3) + sin * K + (1.0 - cos) * (K @ K)
58
+
59
+
60
+ def skew_symmetric(backend, v):
61
+ """Create skew-symmetric matrix from a 3D vector.
62
+
63
+ The skew-symmetric matrix [v]_× satisfies: [v]_× @ u = v × u
64
+
65
+ Parameters
66
+ ----------
67
+ backend : DifferentiableBackend or module
68
+ Backend to use for computation. The ``numpy`` and ``jax.numpy``
69
+ modules work as well.
70
+ v : array, shape (3,) or (..., 3)
71
+ Input vector, or a batch of them.
72
+
73
+ Returns
74
+ -------
75
+ K : array, shape (3, 3) or (..., 3, 3)
76
+ Skew-symmetric matrix, or one per vector.
77
+ """
78
+ return (_CROSS @ v[..., None, :, None])[..., 0]
@@ -1794,6 +1794,7 @@ class CascadedCoords(Coordinates):
1794
1794
  "`relative_coords`'s type should be"
1795
1795
  "skrobot.coordinates.Coordinates, but is {}"
1796
1796
  .format(type(relative_coords)))
1797
+ # The parent setter removes child from its previous parent.
1797
1798
  child.parent = self
1798
1799
  child.newcoords(relative_coords, check_validity=False, relative_coords='local')
1799
1800
  self._descendants.append(child)
@@ -1997,7 +1998,8 @@ class CascadedCoords(Coordinates):
1997
1998
  """Rotate this coordinate.
1998
1999
 
1999
2000
  Rotate this coordinate relative to axis by theta radians
2000
- with respect to wrt.
2001
+ with respect to wrt. The origin of this coordinate is kept for
2002
+ every ``wrt``; only its orientation changes.
2001
2003
 
2002
2004
  Parameters
2003
2005
  ----------
@@ -2006,6 +2008,13 @@ class CascadedCoords(Coordinates):
2006
2008
  axis : str or numpy.ndarray
2007
2009
  'x', 'y', 'z' or vector
2008
2010
  wrt : str or Coordinates
2011
+ Frame in which ``axis`` is expressed.
2012
+
2013
+ - ``'local'`` or ``self``: this coordinate's own axes.
2014
+ - ``'parent'`` or the parent object: the parent's axes. Without
2015
+ a parent, this is the world frame.
2016
+ - ``'world'``: the world axes.
2017
+ - other ``Coordinates``: that coordinate's axes.
2009
2018
  skip_normalization : bool
2010
2019
  if `True`, skip normalization for axis.
2011
2020
 
@@ -2043,22 +2052,9 @@ class CascadedCoords(Coordinates):
2043
2052
  if isinstance(axis, np.ndarray) and axis.shape == (3, 3):
2044
2053
  return self.rotate_with_matrix(theta, wrt)
2045
2054
 
2046
- if wrt == 'local' or wrt == self:
2047
- rotation = rotate_matrix_by_axis_angle(
2048
- self._rotation, theta, axis,
2049
- skip_normalization=skip_normalization)
2050
- return self.newcoords(rotation, self._translation,
2051
- check_validity=False, relative_coords='local')
2052
- elif wrt == 'parent' or wrt == self.parent:
2053
- rotation = rotate_matrix_by_axis_angle(
2054
- self._rotation, theta, axis,
2055
- skip_normalization=skip_normalization)
2056
- return self.newcoords(rotation, self._translation,
2057
- check_validity=False, relative_coords='local')
2058
- else:
2059
- return self.rotate_with_matrix(
2060
- rotation_matrix(theta, axis,
2061
- skip_normalization=skip_normalization), wrt)
2055
+ return self.rotate_with_matrix(
2056
+ rotation_matrix(theta, axis,
2057
+ skip_normalization=skip_normalization), wrt)
2062
2058
 
2063
2059
  def orient_with_matrix(self, rotation_matrix, wrt='world'):
2064
2060
  """Force update this coordinate system's rotation.
@@ -2192,7 +2188,27 @@ class CascadedCoords(Coordinates):
2192
2188
  if not (c is None or coordinates_p(c)):
2193
2189
  raise ValueError('parent should be None or Coordinates. '
2194
2190
  'get type=={}'.format(type(c)))
2191
+ previous = getattr(self, '_parent', None)
2192
+ if previous is c:
2193
+ self._parent = c
2194
+ return
2195
+ # A parent chain through self would make worldcoords() recurse
2196
+ # forever.
2197
+ ancestor = c
2198
+ while ancestor is not None:
2199
+ if ancestor is self:
2200
+ raise ValueError(
2201
+ 'Cannot make {!r} a parent of {!r}: it is already one '
2202
+ 'of its descendants.'.format(c.name, self.name))
2203
+ ancestor = getattr(ancestor, 'parent', None)
2204
+ # Leave the previous parent's descendants, so that re-parenting by
2205
+ # either assoc or a direct assignment leaves no stale entry there.
2206
+ if (isinstance(previous, CascadedCoords)
2207
+ and self in previous._descendants):
2208
+ previous._descendants.remove(self)
2195
2209
  self._parent = c
2210
+ # The cached world pose was taken under the previous parent.
2211
+ self.changed()
2196
2212
 
2197
2213
  def __getstate__(self):
2198
2214
  assert self._worldcoords._hook == self.update
@@ -3,8 +3,12 @@
3
3
  Walks the raw parsed URDF and emits a USD stage with a UsdPhysics
4
4
  articulation -- one rigid body per link (mass + regularized inertia), visual meshes embedded with
5
5
  per-vertex ``displayColor`` (USD renders vertex colours natively, unlike STL/
6
- MJCF), convex collision meshes, and revolute/prismatic/fixed joints (limits +
7
- position drives). A fixed joint welds the base to the world.
6
+ MJCF) and, when the mesh file carries a PBR material (glTF ``metallicFactor`` /
7
+ ``roughnessFactor``, as sw2robot writes them from the SolidWorks appearance), a
8
+ ``UsdPreviewSurface`` material bound to the mesh so Isaac Sim's RTX renderer
9
+ shows aluminium as aluminium; convex collision meshes, and
10
+ revolute/prismatic/fixed joints (limits + position drives). A fixed joint welds
11
+ the base to the world.
8
12
 
9
13
  USD authoring only needs ``usd-core`` (pip), so this runs anywhere -- author the
10
14
  USD on a laptop, load it in Isaac Sim on a GPU box. Entry point: :func:`urdf_to_usd`.
@@ -318,9 +322,33 @@ def _inertia_from_mesh(link, mass, return_reason=False):
318
322
  return None, last_error
319
323
 
320
324
 
325
+ def _submesh_pbr(m):
326
+ """``(metallic, roughness, name)`` of a sub-mesh's PBR material, or None
327
+ when its visual carries no metallic/roughness (vertex colours, COLLADA
328
+ diffuse, no material at all). glTF is the one URDF mesh format that can
329
+ say how shiny a part is; trimesh exposes it as ``visual.material`` with
330
+ ``metallicFactor`` / ``roughnessFactor``."""
331
+ mat = getattr(getattr(m, "visual", None), "material", None)
332
+ if mat is None:
333
+ return None
334
+ metallic = getattr(mat, "metallicFactor", None)
335
+ roughness = getattr(mat, "roughnessFactor", None)
336
+ if metallic is None and roughness is None:
337
+ return None
338
+ try:
339
+ metallic = 0.0 if metallic is None else float(metallic)
340
+ roughness = 0.5 if roughness is None else float(roughness)
341
+ except (TypeError, ValueError):
342
+ return None
343
+ name = getattr(mat, "name", None)
344
+ return (min(max(metallic, 0.0), 1.0), min(max(roughness, 0.0), 1.0),
345
+ str(name) if name else None)
346
+
347
+
321
348
  def _submesh_geometry(mesh_geometry):
322
- """Yield (points, face_counts, face_indices, per_vertex_rgb_or_None, scale)
323
- for each sub-mesh of a URDF Mesh geometry."""
349
+ """Yield (points, face_counts, face_indices, per_vertex_rgb_or_None, pbr)
350
+ for each sub-mesh of a URDF Mesh geometry; ``pbr`` is
351
+ :func:`_submesh_pbr` of that sub-mesh."""
324
352
  import trimesh
325
353
  subs = [m for m in (getattr(mesh_geometry, "meshes", None) or [])
326
354
  if isinstance(m, trimesh.Trimesh) and len(m.faces) > 0]
@@ -360,7 +388,7 @@ def _submesh_geometry(mesh_geometry):
360
388
  c = c / 255.0
361
389
  rgb = [c[:3].tolist()]
362
390
  break
363
- yield pts.tolist(), counts, indices, rgb
391
+ yield pts.tolist(), counts, indices, rgb, _submesh_pbr(m)
364
392
 
365
393
 
366
394
  def urdf_to_usd(urdf, out_path, floating_base=False, drive_stiffness=1000.0,
@@ -797,7 +825,7 @@ def _emit_one(stage, UsdGeom, UsdPhysics, Gf, Vt, link_path, vc, index, collisio
797
825
  # would make a huge degenerate convex hull that NaNs the articulation.
798
826
  if len(submeshes) > 1:
799
827
  cents = [np.mean(np.asarray(pts, dtype=float), axis=0)
800
- if pts else np.zeros(3) for pts, _, _, _ in submeshes]
828
+ if pts else np.zeros(3) for pts, _, _, _, _ in submeshes]
801
829
  med = np.median(np.array(cents), axis=0)
802
830
  dist = [float(np.linalg.norm(c - med)) for c in cents]
803
831
  threshold = max(0.15, 3.0 * float(np.median(dist)))
@@ -806,7 +834,7 @@ def _emit_one(stage, UsdGeom, UsdPhysics, Gf, Vt, link_path, vc, index, collisio
806
834
  all_counts = []
807
835
  all_idx = []
808
836
  offset = 0
809
- for pts, counts, idx, _rgb in submeshes:
837
+ for pts, counts, idx, _rgb, _pbr in submeshes:
810
838
  all_pts.extend(pts)
811
839
  all_counts.extend(counts)
812
840
  all_idx.extend(int(j) + offset for j in idx)
@@ -867,16 +895,18 @@ def _emit_one(stage, UsdGeom, UsdPhysics, Gf, Vt, link_path, vc, index, collisio
867
895
  urdf_rgb = _visual_rgb(vc)
868
896
 
869
897
  # visual: URDF material colour if given, else keep per-submesh colors
870
- for sub_i, (pts, counts, idx, rgb) in enumerate(submeshes):
898
+ for sub_i, (pts, counts, idx, rgb, pbr) in enumerate(submeshes):
871
899
  p = link_path.AppendChild("visual_{}_{}".format(index, sub_i))
872
900
  mesh = UsdGeom.Mesh.Define(stage, p)
873
901
  mesh.CreatePointsAttr(Vt.Vec3fArray([Gf.Vec3f(*v) for v in pts]))
874
902
  mesh.CreateFaceVertexCountsAttr(Vt.IntArray(counts))
875
903
  mesh.CreateFaceVertexIndicesAttr(Vt.IntArray(idx))
876
904
  mesh.AddTransformOp().Set(_mat_to_gf(None, origin))
905
+ lin = None
877
906
  if urdf_rgb is not None:
878
907
  dc = mesh.CreateDisplayColorPrimvar(UsdGeom.Tokens.constant)
879
908
  dc.Set(Vt.Vec3fArray([Gf.Vec3f(*urdf_rgb)]))
909
+ lin = np.asarray([urdf_rgb], dtype=float)
880
910
  elif rgb is not None:
881
911
  # Mesh colours are sRGB too (COLLADA diffuse, glTF baseColorFactor),
882
912
  # so they need the same linearisation as the URDF ones.
@@ -887,6 +917,52 @@ def _emit_one(stage, UsdGeom, UsdPhysics, Gf, Vt, link_path, vc, index, collisio
887
917
  UsdGeom.Tokens.vertex if len(rgb) == len(pts)
888
918
  else UsdGeom.Tokens.constant)
889
919
  dc.Set(Vt.Vec3fArray([Gf.Vec3f(*c) for c in lin.tolist()]))
920
+ if pbr is not None:
921
+ # displayColor alone renders as a dielectric in RTX; the glTF
922
+ # metallic / roughness only reach the renderer through a bound
923
+ # UsdPreviewSurface, with the (one) colour as its diffuseColor.
924
+ diffuse = (np.mean(lin, axis=0).tolist() if lin is not None
925
+ else [0.75, 0.75, 0.75])
926
+ material = _preview_surface(stage, diffuse, pbr)
927
+ from pxr import UsdShade
928
+ UsdShade.MaterialBindingAPI.Apply(mesh.GetPrim()).Bind(material)
929
+
930
+
931
+ _LOOKS_PATH = "/robot/Looks"
932
+
933
+
934
+ def _preview_surface(stage, diffuse_rgb, pbr):
935
+ """A ``UsdPreviewSurface`` material under ``/robot/Looks`` for a linear
936
+ diffuse colour and ``(metallic, roughness, name)``; one prim per distinct
937
+ combination, reused across meshes (a frame of forty aluminium extrusions
938
+ gets one material, not forty)."""
939
+ from pxr import Gf
940
+ from pxr import Sdf
941
+ from pxr import UsdGeom
942
+ from pxr import UsdShade
943
+
944
+ metallic, roughness, name = pbr
945
+ key = "{}_{:02x}{:02x}{:02x}_m{:02d}_r{:02d}".format(
946
+ sanitize_name(name) if name else "material",
947
+ *[int(round(min(max(c, 0.0), 1.0) * 255)) for c in diffuse_rgb[:3]],
948
+ int(round(metallic * 99)), int(round(roughness * 99)))
949
+ path = Sdf.Path(_LOOKS_PATH).AppendChild(key)
950
+ prim = stage.GetPrimAtPath(path)
951
+ if prim.IsValid():
952
+ return UsdShade.Material(prim)
953
+ if not stage.GetPrimAtPath(_LOOKS_PATH).IsValid():
954
+ UsdGeom.Scope.Define(stage, Sdf.Path(_LOOKS_PATH))
955
+ material = UsdShade.Material.Define(stage, path)
956
+ shader = UsdShade.Shader.Define(stage, path.AppendChild("Shader"))
957
+ shader.CreateIdAttr("UsdPreviewSurface")
958
+ shader.CreateInput("diffuseColor", Sdf.ValueTypeNames.Color3f).Set(
959
+ Gf.Vec3f(*[float(c) for c in diffuse_rgb[:3]]))
960
+ shader.CreateInput("metallic", Sdf.ValueTypeNames.Float).Set(float(metallic))
961
+ shader.CreateInput("roughness", Sdf.ValueTypeNames.Float).Set(float(roughness))
962
+ shader.CreateInput("useSpecularWorkflow", Sdf.ValueTypeNames.Int).Set(0)
963
+ material.CreateSurfaceOutput().ConnectToSource(
964
+ shader.ConnectableAPI(), "surface")
965
+ return material
890
966
 
891
967
 
892
968
  def _emit_joint(stage, UsdPhysics, Gf, Sdf, joint, link_path, stiffness, damping,
@@ -124,12 +124,79 @@ class ROS2RobotInterfaceBase(Node):
124
124
  if wait_for_joint_states:
125
125
  self._wait_for_first_joint_state(joint_states_timeout)
126
126
 
127
+ # Action clients and subscriptions add_controller created, so that
128
+ # set_robot can take them down before building the new ones.
129
+ self._controller_entities = []
130
+ self._robot_changed_callbacks = []
127
131
  self.controller_table = {}
128
132
  self.controller_param_table = {}
129
133
  self.controller_type = default_controller
130
134
  self.controller_actions = self.add_controller(
131
135
  self.controller_type, create_actions=True, joint_enable_check=True)
132
136
 
137
+ def set_robot(self, robot, cancel_motion=True):
138
+ """Replace the robot model while the interface is running.
139
+
140
+ For a robot whose joints or kinematics change at runtime -- a tool
141
+ change, a module attached or removed -- the model, the joint-state
142
+ bookkeeping and the controllers have to change together: every
143
+ angle-vector of this interface is indexed by ``robot.joint_list``, and
144
+ the controllers come from :meth:`default_controller`, which subclasses
145
+ compute from that model. Replacing only ``self.robot`` would send the
146
+ new model's angles to the old controllers in the old order.
147
+
148
+ Parameters
149
+ ----------
150
+ robot : skrobot.model.RobotModel
151
+ The new model; copied, as in ``__init__``.
152
+ cancel_motion : bool
153
+ Cancel every goal in flight first (default). A trajectory planned
154
+ for the old model has no meaning for the new one.
155
+
156
+ Returns
157
+ -------
158
+ skrobot.model.RobotModel
159
+ The model that was replaced.
160
+ """
161
+ if cancel_motion:
162
+ self.cancel_angle_vector()
163
+ old = self.robot
164
+ for entity in self._controller_entities:
165
+ if isinstance(entity, ActionClient):
166
+ entity.destroy()
167
+ else:
168
+ self.destroy_subscription(entity)
169
+ self._controller_entities = []
170
+ self.robot = copy.deepcopy(robot)
171
+ self.robot_state = dict()
172
+ self.moving_status = dict()
173
+ self.prev_moving_status = dict()
174
+ self._not_updated_joints = []
175
+ if self._joint_state_msg is not None:
176
+ # Re-file the latest joint_states against the new joint list, and
177
+ # put them in the model: a fresh model holds every joint at its
178
+ # default angle, and anything built from robot.angle_vector() --
179
+ # angle_vector_from_names, for one -- would command those.
180
+ self.joint_state_callback(self._joint_state_msg)
181
+ self.update_robot_state()
182
+ self.joint_action_enable = True
183
+ self.controller_table = {}
184
+ self.controller_param_table = {}
185
+ self.controller_actions = self.add_controller(
186
+ self.controller_type, create_actions=True, joint_enable_check=True)
187
+ for callback in list(self._robot_changed_callbacks):
188
+ callback(old, self.robot)
189
+ return old
190
+
191
+ def add_robot_changed_callback(self, callback):
192
+ """Call ``callback(old_robot, new_robot)`` after each :meth:`set_robot`.
193
+
194
+ For code that holds the model (or links and joints of it): after a
195
+ change those are the old model's and must be fetched again from
196
+ ``self.robot``.
197
+ """
198
+ self._robot_changed_callbacks.append(callback)
199
+
133
200
  def _check_time(self, time, fastest_time, time_scale):
134
201
  """Check and Return send angle vector time
135
202
 
@@ -446,6 +513,7 @@ class ROS2RobotInterfaceBase(Node):
446
513
  action = ControllerActionClient(self,
447
514
  controller_action,
448
515
  controller['action_type'])
516
+ self._controller_entities.append(action._action_client)
449
517
  tmp_actions.append(action)
450
518
  tmp_actions_name.append(controller_action)
451
519
  if 'controller_type' in controller:
@@ -492,16 +560,16 @@ class ROS2RobotInterfaceBase(Node):
492
560
  # Bind the key of this controller now. A bare closure reads
493
561
  # the loop variable when a message arrives, so every
494
562
  # subscription would store under the last controller's key.
495
- self.create_subscription(
563
+ self._controller_entities.append(self.create_subscription(
496
564
  control_msgs.msg.JointTrajectoryControllerState,
497
565
  controller_state_topic_name,
498
566
  partial(self.set_robot_state, controller_state),
499
- 10)
500
- self.create_subscription(
567
+ 10))
568
+ self._controller_entities.append(self.create_subscription(
501
569
  action_msgs.msg.GoalStatusArray,
502
570
  trajectory_status_topic_name,
503
571
  partial(self.set_moving_status, param['controller_type']),
504
- 10)
572
+ 10))
505
573
  else:
506
574
  self.controller_type = controller_type
507
575
  self.controller_table[controller_type] = tmp_actions
@@ -563,8 +631,11 @@ class ROS2RobotInterfaceBase(Node):
563
631
 
564
632
  Parameters
565
633
  ----------
566
- av : list or numpy.ndarray
567
- joint angle vector
634
+ av : list, numpy.ndarray or dict
635
+ joint angle vector, or ``{joint name: angle}`` for the joints to
636
+ move -- the others keep the model's current angles. A dict does
637
+ not depend on the order of ``robot.joint_list``, which changes
638
+ when the model does (see :meth:`set_robot`).
568
639
  time : None or float
569
640
  time to goal in [sec]
570
641
  if designated time is faster than fastest speed, use fastest speed
@@ -587,6 +658,8 @@ class ROS2RobotInterfaceBase(Node):
587
658
  if av is None:
588
659
  self.update_robot_state(wait_until_update=True)
589
660
  return self.robot.angle_vector()
661
+ if isinstance(av, dict):
662
+ av = self.angle_vector_from_names(av)
590
663
  if controller_type is None:
591
664
  controller_type = self.controller_type
592
665
  if controller_type not in self.controller_table:
@@ -619,6 +692,45 @@ class ROS2RobotInterfaceBase(Node):
619
692
  traj_points)
620
693
  return av
621
694
 
695
+ def angle_vector_from_names(self, angles):
696
+ """An angle vector of the current model with ``angles`` set by name.
697
+
698
+ Parameters
699
+ ----------
700
+ angles : dict
701
+ ``{joint name: angle}``.
702
+
703
+ Returns
704
+ -------
705
+ numpy.ndarray
706
+ ``robot.angle_vector()`` with those joints replaced.
707
+
708
+ Raises
709
+ ------
710
+ KeyError
711
+ If a name is not a joint of the current model: dropping it would
712
+ send a motion without the joint the caller asked to move.
713
+ ValueError
714
+ If a joint left out has never been reported on joint_states: its
715
+ angle in the model is a default, not a pose, and the vector would
716
+ send it there.
717
+ """
718
+ names = [joint.name for joint in self.robot.joint_list]
719
+ unknown = sorted(set(angles) - set(names))
720
+ if unknown:
721
+ raise KeyError('not joints of {}: {}'.format(
722
+ self.robot.name, ', '.join(unknown)))
723
+ unmeasured = sorted(set(names) - set(angles) - self._received_joint_names)
724
+ if unmeasured:
725
+ raise ValueError(
726
+ 'never measured, so their angles are defaults, not poses: {}. '
727
+ 'Give them explicitly or wait for joint_states.'.format(
728
+ ', '.join(unmeasured)))
729
+ av = np.array(self.robot.angle_vector(), dtype=np.float64)
730
+ for name, angle in angles.items():
731
+ av[names.index(name)] = angle
732
+ return av
733
+
622
734
  def potentio_vector(self):
623
735
  """Returns current robot angle vector, This method uses caced data."""
624
736
  return self.robot.angle_vector()
@@ -11,6 +11,12 @@ The algorithms support multiple backends (NumPy, JAX) for
11
11
  different performance and autodiff requirements.
12
12
  """
13
13
 
14
+ # Mobile-base placement for several end-effector targets
15
+ from skrobot.kinematics.base_placement import BasePlacementResult
16
+ from skrobot.kinematics.base_placement import find_base_placement
17
+ from skrobot.kinematics.base_placement import set_base_pose
18
+ from skrobot.kinematics.base_placement import vectorized_target
19
+
14
20
  # Differentiable kinematics (backend-agnostic)
15
21
  from skrobot.kinematics.differentiable import create_batch_ik_solver
16
22
  from skrobot.kinematics.differentiable import create_dynamic_limit_mask
@@ -18,6 +24,10 @@ from skrobot.kinematics.differentiable import extract_fk_parameters
18
24
  from skrobot.kinematics.differentiable import forward_kinematics
19
25
  from skrobot.kinematics.differentiable import forward_kinematics_ee
20
26
 
27
+ # Inverse reachability map: base poses that reach a hand pose
28
+ from skrobot.kinematics.inverse_reachability_map import BaseCandidates
29
+ from skrobot.kinematics.inverse_reachability_map import InverseReachabilityMap
30
+
21
31
  # Loop-closure solving for cut kinematic loops
22
32
  from skrobot.kinematics.loop_closure import LoopClosureSolver
23
33
 
@@ -33,4 +43,10 @@ __all__ = [
33
43
  'create_dynamic_limit_mask',
34
44
  'LoopClosureSolver',
35
45
  'ReachabilityMap',
46
+ 'BasePlacementResult',
47
+ 'find_base_placement',
48
+ 'set_base_pose',
49
+ 'vectorized_target',
50
+ 'BaseCandidates',
51
+ 'InverseReachabilityMap',
36
52
  ]