Skip to content

IKPy v4.3.0

Choose a tag to compare

@Phylliade Phylliade released this 27 Oct 19:22
· 5 commits to master since this release
v4.3.0
76852e9

What's new in v4.3.0

🎯 A new import API: base and tip

The way a chain is imported from a robot description has been redesigned. Until now, Chain.from_urdf_file took base_elements, an ordered list of link and joint names to follow, alternating links and joints, with base_element_type to say what the first name was, and the parser went on with the first child of each element once the list was exhausted, which picked a branch by file order; from_mjcf_file and from_bvh_file each had their own variant of it. All three now share one vocabulary: a robot description is a tree, and the path from a base to a tip is unique, so the two names are all it takes to select a chain, in every format:

# Before
chain = Chain.from_urdf_file("baxter.urdf", base_elements=["base", "torso_t0", "torso", "left_torso_arm_mount", "left_arm_mount", "left_s0", ...], last_link_vector=[0, 0, 0.1])

# Now
chain = Chain.from_urdf_file("baxter.urdf", base="base", tip="left_gripper", tip_offset=[0, 0, 0.1])
chain = Chain.from_mjcf_file("ur5e.xml", base="base", tip="wrist_3_link")
chain = Chain.from_bvh_file("walk.bvh", base="Hips", tip="LeftHand")
  • base is the element where the chain starts, tip the element where it ends; the path in between is found automatically. base defaults to the root of the file and tip to the only leaf below base; when the tree branches, the error lists the leaves to choose from, instead of silently following the first child.
  • In a URDF, base and tip name a link or a joint. When a joint and its child link share a name, the name means the link, and {"name": "left_hand", "type": "joint"} says otherwise.
  • tip_offset replaces last_link_vector, same meaning: a fixed translation at the end of the chain, typically the tool center point.
  • The former base_elements, base_element_type and last_link_vector keep working exactly as before, with a DeprecationWarning that shows the equivalent call; they will be removed in 5.0. Mixing the two forms raises.
  • The selection arguments are now keyword-only: Chain.from_urdf_file(file, ["base"]) raises a TypeError instead of guessing.
  • Chain JSON files written by to_json_file use a v2 format with base, tip and tip_offset; v1 files, such as the ones shipped in resources/, still load, without a warning.
  • ikpy.selection holds the shared vocabulary and the tree helpers behind the three parsers.

🔀 Multi-start: several starting points, the best solution

The optimizer is local and converges to the solution closest to its starting point. initial_position now also accepts several starting points, and inverse_kinematics returns the best of the solutions reached from them:

chain.inverse_kinematics(target, initial_position=q)        # unchanged: one configuration, one solution
chain.inverse_kinematics(target, initial_position=20)       # 20 starts drawn in the joint limits
chain.inverse_kinematics(target, initial_position={"points": [q], "n": 9, "seed": 0, "around": q, "radius": 0.5})
chain.inverse_kinematics(target, initial_position=starts)   # an array of shape (n_starts, n_links)

To get every distinct solution of a target rather than the best one (elbow up and elbow down, wrist flipped...), chain._inverse_kinematics_solutions_frame(frame, initial_position=20, max_error=1e-3) returns them sorted by error; it is kept out of the main API but documented for that use. Closes #144.

🛤️ Trajectories

inverse_kinematics_trajectory_frame solves a sequence of frames, each step starting from the previous solution, so the joint motion follows one branch of solutions instead of jumping, and returns a (n_steps, n_links) array. geometry.interpolate_frames builds the frames between two poses (straight line, constant-speed rotation), and any list of frames works, such as the waypoints of a path planner. A multi-start on the first step picks the branch the trajectory then follows; regularization_parameter trades a little accuracy for a smoother joint motion. Closes #129, #158 and #133.

🤖 URDF conventions aligned on ROS

Checked against the Panda, Baxter, KUKA iiwa, xArm6, Husky, Laikago and R2D2 descriptions: a non-unit joint axis is normalized with a warning (it used to give a wrong rotation in silence), floating and planar joints are treated as fixed joints with a warning, as KDL does, and a xacro file is refused with a message saying to expand it first. The Panda description joins the resources. mimic joints are the remaining gap, tracked in #188.

🧰 Helpers

ikpy.inverse_kinematics.target_error gives the residual of a configuration as the solver sees it, Chain.sample_initial_positions draws starting points inside the joint limits, and ikpy.selection holds the tree helpers shared by the parsers.