scikit-robot 0.4.1__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.
- {scikit_robot-0.4.1/scikit_robot.egg-info → scikit_robot-0.4.2}/PKG-INFO +1 -1
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/pyproject.toml +1 -1
- {scikit_robot-0.4.1 → scikit_robot-0.4.2/scikit_robot.egg-info}/PKG-INFO +1 -1
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/scikit_robot.egg-info/SOURCES.txt +3 -0
- scikit_robot-0.4.2/skrobot/backend/math_utils.py +78 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/coordinates/base.py +33 -17
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/kinematics/__init__.py +16 -0
- scikit_robot-0.4.2/skrobot/kinematics/_base_placement_jax.py +268 -0
- scikit_robot-0.4.2/skrobot/kinematics/base_placement.py +1340 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/kinematics/differentiable.py +63 -60
- scikit_robot-0.4.2/skrobot/kinematics/inverse_reachability_map.py +422 -0
- scikit_robot-0.4.1/skrobot/backend/math_utils.py +0 -74
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/LICENSE +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/MANIFEST.in +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/README.md +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/scikit_robot.egg-info/dependency_links.txt +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/scikit_robot.egg-info/entry_points.txt +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/scikit_robot.egg-info/not-zip-safe +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/scikit_robot.egg-info/requires.txt +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/scikit_robot.egg-info/top_level.txt +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/setup.cfg +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/__init__.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/_lazy_imports.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/apps/__init__.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/apps/canonicalize_urdf.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/apps/change_urdf_root.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/apps/cli.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/apps/convert_urdf_mesh.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/apps/convert_urdf_to_mjcf.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/apps/convert_urdf_to_primitives.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/apps/convert_wheel_collision.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/apps/extract_sub_urdf.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/apps/generate_robot_class.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/apps/modularize_urdf.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/apps/scale_urdf.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/apps/transform_urdf.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/apps/urdf_hash.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/apps/urdf_tree.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/apps/visualize_mesh.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/apps/visualize_urdf.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/assembly/__init__.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/assembly/module_assembly.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/assembly/module_registry.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/backend/__init__.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/backend/jax_backend.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/backend/numpy_backend.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/backend/registry.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/collision/__init__.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/collision/distance.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/collision/geometry.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/collision/robot_collision.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/collision/self_collision.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/coordinates/__init__.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/coordinates/geo.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/coordinates/math.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/data/__init__.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/data/kuka_description/kuka.urdf +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/data/kuka_description/meshes/finger_base_left.stl +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/data/kuka_description/meshes/finger_base_right.stl +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/data/kuka_description/meshes/finger_tip_left.stl +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/data/kuka_description/meshes/finger_tip_right.stl +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/data/kuka_description/meshes/link_0.mtl +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/data/kuka_description/meshes/link_0.obj +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/data/kuka_description/meshes/link_0.stl +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/data/kuka_description/meshes/link_1.mtl +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/data/kuka_description/meshes/link_1.obj +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/data/kuka_description/meshes/link_1.stl +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/data/kuka_description/meshes/link_2.mtl +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/data/kuka_description/meshes/link_2.obj +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/data/kuka_description/meshes/link_2.stl +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/data/kuka_description/meshes/link_3.mtl +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/data/kuka_description/meshes/link_3.obj +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/data/kuka_description/meshes/link_3.stl +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/data/kuka_description/meshes/link_4.mtl +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/data/kuka_description/meshes/link_4.obj +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/data/kuka_description/meshes/link_4.stl +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/data/kuka_description/meshes/link_5.mtl +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/data/kuka_description/meshes/link_5.obj +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/data/kuka_description/meshes/link_5.stl +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/data/kuka_description/meshes/link_6.mtl +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/data/kuka_description/meshes/link_6.obj +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/data/kuka_description/meshes/link_6.stl +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/data/kuka_description/meshes/link_7.mtl +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/data/kuka_description/meshes/link_7.obj +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/data/kuka_description/meshes/link_7.stl +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/data/robot_descriptions/urdf/r8_6.urdf +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/data/ros_config_templates/CMakeLists.txt.ros2.template +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/data/ros_config_templates/gazebo.launch.py.template +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/data/ros_config_templates/gazebo_moveit.launch.py.template +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/data/ros_config_templates/isaac_fjt_server.py.template +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/data/ros_config_templates/moveit.rviz.template +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/data/ros_config_templates/package.xml.ros2.template +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/data/ros_config_templates/ros2_control.xacro.joint.template +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/data/ros_config_templates/ros2_control.xacro.template +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/data/ros_config_templates/setup_assistant.template +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/dynamics/__init__.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/dynamics/differentiable.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/dynamics/gravity.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/export/__init__.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/export/contact_links.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/export/isaac/__init__.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/export/isaac/fjt_server.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/export/task.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/export/usd.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/interfaces/__init__.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/interfaces/_pybullet.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/interfaces/ros/__init__.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/interfaces/ros/base.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/interfaces/ros/move_base.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/interfaces/ros/nextage.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/interfaces/ros/panda.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/interfaces/ros/pr2.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/interfaces/ros/tf_utils.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/interfaces/ros/transform_listener.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/interfaces/ros2/__init__.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/interfaces/ros2/base.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/interfaces/ros2/gripper.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/interfaces/ros2/panda.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/kinematics/loop_closure.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/kinematics/reachability_map.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/model/__init__.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/model/joint.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/model/joint_limit_table.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/model/link.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/model/primitives.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/model/robot_model.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/model/skeleton.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/models/__init__.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/models/aero.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/models/differential_wrist_sample.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/models/fetch.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/models/g1.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/models/griphis.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/models/hydrus.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/models/jaxon_jvrc.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/models/jedy.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/models/kuka.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/models/nextage.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/models/panda.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/models/pr2.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/models/r8_6.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/models/tycoon.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/models/urdf.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/planner/__init__.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/planner/collision_checker.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/planner/inverse_kinematics_optimization.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/planner/sqp_based.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/planner/swept_sphere.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/planner/trajectory_optimization/__init__.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/planner/trajectory_optimization/collision.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/planner/trajectory_optimization/fk_utils.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/planner/trajectory_optimization/gridsdf_collision.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/planner/trajectory_optimization/problem.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/planner/trajectory_optimization/residuals.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/planner/trajectory_optimization/solvers/__init__.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/planner/trajectory_optimization/solvers/augmented_lagrangian.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/planner/trajectory_optimization/solvers/base.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/planner/trajectory_optimization/solvers/gradient_descent.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/planner/trajectory_optimization/solvers/jaxls_solver.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/planner/trajectory_optimization/solvers/scipy_solver.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/planner/trajectory_optimization/solvers/solver_utils.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/planner/trajectory_optimization/trajectory.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/planner/trajectory_optimization/world_surface_collision.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/planner/utils.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/pycompat.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/sdf/__init__.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/sdf/signed_distance_function.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/urdf/__init__.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/urdf/aggregate.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/urdf/canonicalize.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/urdf/compare.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/urdf/extract_sub_urdf.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/urdf/flip_axis.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/urdf/hash.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/urdf/link_origins.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/urdf/llm_grouping.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/urdf/merge_fixed_links.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/urdf/modularize_urdf.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/urdf/primitives_converter.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/urdf/robot_class_generator.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/urdf/ros_config/__init__.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/urdf/ros_config/export.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/urdf/ros_config/gazebo_generator.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/urdf/ros_config/moveit_generator.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/urdf/ros_config/moveit_package.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/urdf/ros_config/urdf_parser.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/urdf/ros_package.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/urdf/ros_package_exporter.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/urdf/sanitize.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/urdf/scale_urdf.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/urdf/structure.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/urdf/transform_urdf.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/urdf/wheel_collision_converter.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/urdf/xml_root_link_changer.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/utils/__init__.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/utils/_blender_decimate_core.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/utils/_blender_remesh_core.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/utils/archive.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/utils/blender_mesh.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/utils/checksum.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/utils/convex_decomposition.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/utils/draco.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/utils/inertia.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/utils/listify.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/utils/mesh.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/utils/mjcf_converter.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/utils/package.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/utils/primitive_fitting.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/utils/urdf.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/utils/urdf_mesh.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/utils/video.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/utils/visualization.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/viewers/__init__.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/viewers/_base.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/viewers/_manipulability_ellipse.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/viewers/_mitsuba.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/viewers/_notebook.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/viewers/_path_utils.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/viewers/_pyrender.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/viewers/_trimesh.py +0 -0
- {scikit_robot-0.4.1 → scikit_robot-0.4.2}/skrobot/viewers/_viser.py +0 -0
|
@@ -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
|
-
|
|
2047
|
-
|
|
2048
|
-
|
|
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
|
|
@@ -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
|
]
|
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
"""JAX version of the shared-base Levenberg-Marquardt loop.
|
|
2
|
+
|
|
3
|
+
The NumPy loop in :mod:`skrobot.kinematics.base_placement` drops finished
|
|
4
|
+
starts from the batch every iteration, which keeps the work small but
|
|
5
|
+
spends most of its time in Python and in small ``einsum`` calls. Here one
|
|
6
|
+
iteration -- linearize, Schur step, trial residual, accept or reject --
|
|
7
|
+
is a single jitted function over a fixed-size batch. The batch shrinks to
|
|
8
|
+
the next power of sixteen when fifteen sixteenths of it have finished,
|
|
9
|
+
so a solve compiles for two or three sizes only; each costs seconds,
|
|
10
|
+
which is why the sizes are spaced so far apart.
|
|
11
|
+
|
|
12
|
+
Everything runs in float64, inside ``jax.enable_x64`` so the global
|
|
13
|
+
setting is left alone. In float32 the accept and stall tests round
|
|
14
|
+
differently, and the solve takes a different path than the NumPy one.
|
|
15
|
+
|
|
16
|
+
Targets that follow the base are evaluated on the host, as in the NumPy
|
|
17
|
+
loop, together with their finite-difference derivative; within one
|
|
18
|
+
iteration the trial step moves them along that derivative.
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
import numpy as np
|
|
22
|
+
|
|
23
|
+
from skrobot.backend.math_utils import rodrigues_rotation
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def _enable_x64(jax):
|
|
27
|
+
"""Context manager turning on float64 for the code inside it.
|
|
28
|
+
|
|
29
|
+
It is ``jax.enable_x64`` in current JAX and only
|
|
30
|
+
``jax.experimental.enable_x64`` up to 0.7.
|
|
31
|
+
"""
|
|
32
|
+
if hasattr(jax, 'enable_x64'):
|
|
33
|
+
return jax.enable_x64(True)
|
|
34
|
+
from jax.experimental import enable_x64
|
|
35
|
+
return enable_x64(True)
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class JaxLevenbergMarquardt(object):
|
|
39
|
+
"""Jitted LM iterations for one :class:`_SharedBaseProblem`."""
|
|
40
|
+
|
|
41
|
+
def __init__(self, problem, thre, rthre, max_pos_step, max_rot_step,
|
|
42
|
+
bounds):
|
|
43
|
+
import jax
|
|
44
|
+
import jax.numpy as jnp
|
|
45
|
+
|
|
46
|
+
from skrobot.kinematics.base_placement import _clip_joints
|
|
47
|
+
from skrobot.kinematics.base_placement import _clip_rows
|
|
48
|
+
from skrobot.kinematics.base_placement import _cost
|
|
49
|
+
from skrobot.kinematics.base_placement import _margin_terms
|
|
50
|
+
from skrobot.kinematics.base_placement import _place_on_base
|
|
51
|
+
from skrobot.kinematics.base_placement import _pose_residual
|
|
52
|
+
from skrobot.kinematics.base_placement import _residual_jacobians
|
|
53
|
+
from skrobot.kinematics.base_placement import _schur_step
|
|
54
|
+
from skrobot.kinematics.differentiable import compute_geometric_jacobian_jax
|
|
55
|
+
|
|
56
|
+
self.jax = jax
|
|
57
|
+
self.jnp = jnp
|
|
58
|
+
self.problem = problem
|
|
59
|
+
fk = problem.fk_params
|
|
60
|
+
n_joints = fk['n_joints']
|
|
61
|
+
non_mimic = problem.non_mimic
|
|
62
|
+
n_opt = problem.n_opt
|
|
63
|
+
n_targets = problem.n_targets
|
|
64
|
+
|
|
65
|
+
jac_one = jax.vmap(lambda a: compute_geometric_jacobian_jax(a, fk))
|
|
66
|
+
row_mask = jnp.asarray(problem.row_mask)
|
|
67
|
+
tolerance = (None if problem.rotation_tolerance is None
|
|
68
|
+
else jnp.asarray(problem.rotation_tolerance))
|
|
69
|
+
# Kept in NumPy: only its pattern is read, at trace time.
|
|
70
|
+
base_frame = problem.base_frame
|
|
71
|
+
lower = jnp.asarray(problem.lower)
|
|
72
|
+
upper = jnp.asarray(problem.upper)
|
|
73
|
+
unbounded = jnp.asarray(problem.unbounded)
|
|
74
|
+
bounded = jnp.asarray(problem.bounded)
|
|
75
|
+
span = jnp.asarray(problem.span)
|
|
76
|
+
margin_weight = problem.margin_weight
|
|
77
|
+
has_moving = bool(problem.target_fns)
|
|
78
|
+
moving_idx = jnp.asarray([i for i, _ in problem.target_fns],
|
|
79
|
+
dtype=jnp.int32)
|
|
80
|
+
# The fixed targets stay on the device; only the few that follow
|
|
81
|
+
# the base cross over each iteration.
|
|
82
|
+
static_pos = jnp.asarray(problem.target_pos)
|
|
83
|
+
static_rot = jnp.asarray(problem.target_rot)
|
|
84
|
+
lo = None if bounds is None else jnp.asarray(bounds[0])
|
|
85
|
+
hi = None if bounds is None else jnp.asarray(bounds[1])
|
|
86
|
+
|
|
87
|
+
def chain(q):
|
|
88
|
+
n_cand = q.shape[0]
|
|
89
|
+
angles = jnp.zeros((n_cand * n_targets, n_joints), q.dtype)
|
|
90
|
+
angles = angles.at[:, non_mimic].set(q.reshape(-1, n_opt))
|
|
91
|
+
jac, pos, rot = jac_one(angles)
|
|
92
|
+
return (jac.reshape(n_cand, n_targets, 6, n_opt),
|
|
93
|
+
pos.reshape(n_cand, n_targets, 3),
|
|
94
|
+
rot.reshape(n_cand, n_targets, 3, 3))
|
|
95
|
+
|
|
96
|
+
def residual(meas_pos, meas_rot, target_pos, target_rot):
|
|
97
|
+
return _pose_residual(meas_pos, meas_rot, target_pos, target_rot, row_mask,
|
|
98
|
+
tolerance, jnp)
|
|
99
|
+
|
|
100
|
+
def linearize(bases, q, target_pos, target_rot, dt):
|
|
101
|
+
jac, pos, rot = chain(q)
|
|
102
|
+
(meas_pos, meas_rot, world_pos, world_rot, base_rot,
|
|
103
|
+
base_pos) = _place_on_base(pos, rot, bases, base_frame, jnp)
|
|
104
|
+
err = residual(meas_pos, meas_rot, target_pos, target_rot)
|
|
105
|
+
base_jac, arm_jac = _residual_jacobians(
|
|
106
|
+
err, jac, world_pos, world_rot, base_rot, base_pos,
|
|
107
|
+
base_frame, row_mask, tolerance, dt, jnp)
|
|
108
|
+
return err, base_jac, arm_jac
|
|
109
|
+
|
|
110
|
+
def margin_terms(q, floor):
|
|
111
|
+
return _margin_terms(q, floor, lower, upper, span, bounded,
|
|
112
|
+
margin_weight, jnp)
|
|
113
|
+
|
|
114
|
+
def iterate(state, base_weight, mpos, mrot, mdt):
|
|
115
|
+
bases, q, damping, stalls, done, weight, floor = state
|
|
116
|
+
n_cand = bases.shape[0]
|
|
117
|
+
target_pos = jnp.broadcast_to(static_pos, (n_cand,) + static_pos.shape)
|
|
118
|
+
target_rot = jnp.broadcast_to(static_rot, (n_cand,) + static_rot.shape)
|
|
119
|
+
dt = None
|
|
120
|
+
if has_moving:
|
|
121
|
+
target_pos = target_pos.at[:, moving_idx].set(mpos)
|
|
122
|
+
target_rot = target_rot.at[:, moving_idx].set(mrot)
|
|
123
|
+
dt = jnp.zeros((n_cand, n_targets, 6, 3)).at[
|
|
124
|
+
:, moving_idx].set(mdt)
|
|
125
|
+
err, bj, aj = linearize(bases, q, target_pos, target_rot, dt)
|
|
126
|
+
m_err, m_jac = margin_terms(q, floor)
|
|
127
|
+
cost = _cost(err * weight[..., None], m_err, jnp)
|
|
128
|
+
pos_norm = jnp.linalg.norm(err[..., :3], axis=-1)
|
|
129
|
+
rot_norm = jnp.linalg.norm(err[..., 3:], axis=-1)
|
|
130
|
+
reached = (pos_norm < thre) & (rot_norm < rthre)
|
|
131
|
+
done = done | (jnp.all(reached | (weight == 0), axis=1)
|
|
132
|
+
& ~jnp.any(m_err > 0, axis=(1, 2)))
|
|
133
|
+
done = done | (damping >= 1e4) | (stalls >= 5)
|
|
134
|
+
w = weight[..., None]
|
|
135
|
+
d_base, d_arm = _schur_step(
|
|
136
|
+
_clip_rows(err, max_pos_step, max_rot_step, jnp) * w,
|
|
137
|
+
bj * w[..., None], aj * w[..., None], damping, base_weight,
|
|
138
|
+
m_err, m_jac, jnp)
|
|
139
|
+
new_bases = bases.at[:, :3].add(d_base)
|
|
140
|
+
if lo is not None:
|
|
141
|
+
new_bases = new_bases.at[:, :2].set(
|
|
142
|
+
jnp.clip(new_bases[:, :2], lo, hi))
|
|
143
|
+
new_q = _clip_joints(q + d_arm, lower, upper, unbounded, jnp)
|
|
144
|
+
step = new_bases[:, :3] - bases[:, :3]
|
|
145
|
+
if has_moving:
|
|
146
|
+
# First-order move of the base-following targets.
|
|
147
|
+
new_target_pos = target_pos + jnp.einsum(
|
|
148
|
+
'knia,ka->kni', dt[..., :3, :], step)
|
|
149
|
+
twist = jnp.einsum('knia,ka->kni', dt[..., 3:, :], step)
|
|
150
|
+
new_target_rot = rodrigues_rotation(
|
|
151
|
+
jnp, twist, jnp.linalg.norm(twist, axis=-1)) @ target_rot
|
|
152
|
+
else:
|
|
153
|
+
new_target_pos, new_target_rot = target_pos, target_rot
|
|
154
|
+
_, pos, rot = chain(new_q)
|
|
155
|
+
mp, mr, _, _, _, _ = _place_on_base(pos, rot, new_bases,
|
|
156
|
+
base_frame, jnp)
|
|
157
|
+
new_err = residual(mp, mr, new_target_pos, new_target_rot)
|
|
158
|
+
new_m_err, _ = margin_terms(new_q, floor)
|
|
159
|
+
new_cost = _cost(new_err * weight[..., None], new_m_err, jnp)
|
|
160
|
+
accept = (new_cost < cost) & ~done
|
|
161
|
+
damping = jnp.where(accept, jnp.maximum(damping * 0.5, 1e-6),
|
|
162
|
+
jnp.minimum(damping * 4.0, 1e4))
|
|
163
|
+
small = cost - new_cost < 1e-3 * jnp.maximum(cost, 1e-12)
|
|
164
|
+
stalls = jnp.where(accept, jnp.where(small, stalls + 1, 0),
|
|
165
|
+
stalls)
|
|
166
|
+
bases = jnp.where(accept[:, None], new_bases, bases)
|
|
167
|
+
q = jnp.where(accept[:, None, None], new_q, q)
|
|
168
|
+
return (bases, q, damping, stalls, done, weight, floor)
|
|
169
|
+
|
|
170
|
+
self._iterate = jax.jit(iterate)
|
|
171
|
+
self._has_moving = has_moving
|
|
172
|
+
|
|
173
|
+
def _moving(self, bases):
|
|
174
|
+
"""Host-side poses ``(K, D, 3)``, ``(K, D, 3, 3)`` of the targets
|
|
175
|
+
that follow the base, and their base derivative ``(K, D, 6, 3)``."""
|
|
176
|
+
problem = self.problem
|
|
177
|
+
n_cand = bases.shape[0]
|
|
178
|
+
if not problem.target_fns:
|
|
179
|
+
return (np.zeros((n_cand, 0, 3)), np.zeros((n_cand, 0, 3, 3)),
|
|
180
|
+
np.zeros((n_cand, 0, 6, 3)))
|
|
181
|
+
pos, rot = problem._moving_targets(bases)
|
|
182
|
+
return pos, rot, problem.moving_target_jacobian(bases)
|
|
183
|
+
|
|
184
|
+
def run(self, bases, q, active, stop, base_weight, margin_target):
|
|
185
|
+
"""Iterate in place on ``bases`` / ``q``; return the final error."""
|
|
186
|
+
with _enable_x64(self.jax):
|
|
187
|
+
self._run(bases, q, active, stop, base_weight, margin_target)
|
|
188
|
+
return self.problem.residual(bases, q)
|
|
189
|
+
|
|
190
|
+
def _run(self, bases, q, active, stop, base_weight, margin_target):
|
|
191
|
+
n_cand = bases.shape[0]
|
|
192
|
+
floor = (np.zeros(n_cand) if margin_target is None
|
|
193
|
+
else np.asarray(margin_target, dtype=np.float64))
|
|
194
|
+
weight = active.astype(np.float64)
|
|
195
|
+
damping = np.full(n_cand, 1e-2)
|
|
196
|
+
stalls = np.zeros(n_cand, dtype=np.int64)
|
|
197
|
+
done = np.zeros(n_cand, dtype=bool)
|
|
198
|
+
base_weight = self.jax.device_put(
|
|
199
|
+
np.asarray(base_weight, dtype=np.float64))
|
|
200
|
+
|
|
201
|
+
jax = self.jax
|
|
202
|
+
rows = np.arange(n_cand)
|
|
203
|
+
size = _bucket(n_cand)
|
|
204
|
+
state = None
|
|
205
|
+
moving = None
|
|
206
|
+
for _ in range(stop):
|
|
207
|
+
if state is None:
|
|
208
|
+
padded = _pad(rows, size)
|
|
209
|
+
# One transfer for the lot; jnp.asarray per array costs a
|
|
210
|
+
# dispatch each.
|
|
211
|
+
state = jax.device_put((
|
|
212
|
+
bases[padded], q[padded], damping[padded],
|
|
213
|
+
stalls[padded], done[padded] | (padded < 0),
|
|
214
|
+
weight[padded], floor[padded]))
|
|
215
|
+
host_bases = bases[padded].copy()
|
|
216
|
+
host_moving = self._moving(host_bases)
|
|
217
|
+
moving = jax.device_put(host_moving)
|
|
218
|
+
elif self._has_moving:
|
|
219
|
+
# Only rows whose base moved need their targets again; a
|
|
220
|
+
# rejected step leaves the base where it was.
|
|
221
|
+
new_bases = np.asarray(state[0])
|
|
222
|
+
changed = np.any(new_bases != host_bases, axis=1)
|
|
223
|
+
if np.any(changed):
|
|
224
|
+
fresh = self._moving(new_bases[changed])
|
|
225
|
+
for held, new in zip(host_moving, fresh):
|
|
226
|
+
held[changed] = new
|
|
227
|
+
host_bases = new_bases.copy()
|
|
228
|
+
moving = jax.device_put(host_moving)
|
|
229
|
+
state = self._iterate(state, base_weight, *moving)
|
|
230
|
+
live = ~np.asarray(state[4])[:len(rows)]
|
|
231
|
+
if not np.any(live):
|
|
232
|
+
break
|
|
233
|
+
if size > 16 and np.count_nonzero(live) <= size // 16:
|
|
234
|
+
# Shrink the batch: write the rows back and repack the
|
|
235
|
+
# ones still running.
|
|
236
|
+
self._write_back(state, rows, bases, q, damping, stalls,
|
|
237
|
+
done)
|
|
238
|
+
rows = rows[live]
|
|
239
|
+
size = _bucket(len(rows))
|
|
240
|
+
state = None
|
|
241
|
+
if state is not None:
|
|
242
|
+
self._write_back(state, rows, bases, q, damping, stalls, done)
|
|
243
|
+
|
|
244
|
+
@staticmethod
|
|
245
|
+
def _write_back(state, rows, bases, q, damping, stalls, done):
|
|
246
|
+
n = len(rows)
|
|
247
|
+
bases[rows] = np.asarray(state[0])[:n]
|
|
248
|
+
q[rows] = np.asarray(state[1])[:n]
|
|
249
|
+
damping[rows] = np.asarray(state[2])[:n]
|
|
250
|
+
stalls[rows] = np.asarray(state[3])[:n]
|
|
251
|
+
done[rows] = np.asarray(state[4])[:n]
|
|
252
|
+
|
|
253
|
+
|
|
254
|
+
def _bucket(n):
|
|
255
|
+
"""Smallest power of sixteen, at least 16, holding ``n`` rows."""
|
|
256
|
+
size = 16
|
|
257
|
+
while size < n:
|
|
258
|
+
size *= 16
|
|
259
|
+
return size
|
|
260
|
+
|
|
261
|
+
|
|
262
|
+
def _pad(rows, size):
|
|
263
|
+
"""``rows`` padded to ``size`` with -1, which marks a dummy row.
|
|
264
|
+
|
|
265
|
+
Index -1 picks the last row of the batch, a real row whose copy is
|
|
266
|
+
flagged done and never written back.
|
|
267
|
+
"""
|
|
268
|
+
return np.concatenate([rows, np.full(size - len(rows), -1)])
|