Repository navigation
IKPy v4.2.0
What's new in v4.2.0
🦴 BVH motion capture files
IKPy now reads BVH (Biovision Hierarchy) files, the common format of motion capture data. Any path of the skeleton becomes a chain, and the motion of the file can be replayed on it:
from ikpy.chain import Chain
from ikpy.bvh import BVH
# From the hips to the left hand; the joints in between are filled in automatically
chain = Chain.from_bvh_file("walk.bvh", base_elements=["Hips", "LeftHand"], scale=0.01)
trajectory, frame_time = BVH.get_bvh_motion("walk.bvh", base_elements=["Hips", "LeftHand"], scale=0.01)
hand_frames = [chain.forward_kinematics(joints) for joints in trajectory]Each channel of a joint becomes one link (Hips_Zrotation, Hips_Xrotation...), so the rotation order of every joint is reproduced exactly, whatever the exporter. Position channels are supported on any joint, as in Mixamo exports, and the zero joint vector is the rest pose of the skeleton. BVH files have no unit: scale converts them to meters. The implementation was checked against pybvh's forward kinematics on CMU, Mixamo, mocapbank, MakeHuman and SnapMoGen captures. Closes #91, requested by @gemlongman.
🔄 URDF continuous joints
A continuous joint is a revolute joint without limits, and IKPy now loads it as such instead of raising Unknown joint type. This unblocks TIAGo, ABB and many ROS robots. Thanks to @smoltafet (#181), closes #134.
📐 Default joint axis
A revolute or prismatic joint whose <axis> element is absent now uses the URDF default (1, 0, 0), like urdfdom, instead of failing in validation. An <axis> without its xyz attribute gets the same default with a warning. Thanks to @smoltafet (#182), closes #180.
🧭 Orientation conversions
ikpy.utils.geometry converts the rotation part of a frame to and from the representations of ROS, Unity and Blender:
from ikpy.utils import geometry
frame = chain.forward_kinematics(joints)
quaternion = geometry.rotation_matrix_to_quaternion(frame) # (x, y, z, w)
quaternion = geometry.rotation_matrix_to_quaternion(frame, scalar_first=True) # (w, x, y, z)
roll, pitch, yaw = geometry.rotation_matrix_to_rpy(frame) # URDF convention
target_orientation = geometry.quaternion_to_rotation_matrix(quaternion)
joints = chain.inverse_kinematics(target_position, target_orientation, orientation_mode="all")rotation_matrix_to_euler / euler_to_rotation_matrix handle any axis sequence. Closes #103.
📏 Denavit-Hartenberg links
DHLink accepts convention="modified" (Craig's convention, Rx(alpha) Tx(a) Rz(theta) Tz(d)) next to the classic one. It also keeps its name now: it used to be overwritten by use_symbolic_matrix. Closes #55 and #149.
🔧 Fixes
- MJCF: a multi-body
base_elementspath such as["base", "right_arm"]produced a chain with only the origin link. Thanks to @YaoxinHuang (#179). - URDF: when a link or joint of
base_elementsis not found, the error lists the available names and points atbase_elements. Closes #156. tutorials.mdlinks the notebooks from the current tree, and says that the two Poppy notebooks need pypot and a simulator (#146).
⚠️ Known issue
The JAX backend silently treats DHLink as a fixed joint (#183). Use backend="numpy" for DH chains until it is fixed.