Mobile IKΒΆ

Same as 01_basic_ik.py, but with a mobile base!

All examples can be run by first cloning the PyRoki repository, which includes the pyroki_snippets implementation details.

 1import time
 2import viser
 3from robot_descriptions.loaders.yourdfpy import load_robot_description
 4import numpy as np
 5
 6import pyroki as pk
 7from viser.extras import ViserUrdf
 8import pyroki_snippets as pks
 9
10
11def main():
12    """Main function for IK with a mobile base.
13    The base is fixed along the xy plane, and is biased towards being at the origin.
14    """
15
16    urdf = load_robot_description("fetch_description")
17    target_link_name = "gripper_link"
18
19    # Create robot.
20    robot = pk.Robot.from_urdf(urdf)
21
22    # Set up visualizer.
23    server = viser.ViserServer()
24    server.scene.add_grid("/ground", width=2, height=2)
25    base_frame = server.scene.add_frame("/base", show_axes=False)
26    urdf_vis = ViserUrdf(server, urdf, root_node_name="/base")
27
28    # Create interactive controller with initial position.
29    ik_target = server.scene.add_transform_controls(
30        "/ik_target", scale=0.2, position=(0.61, 0.0, 0.56), wxyz=(0, 0.707, 0, -0.707)
31    )
32    timing_handle = server.gui.add_number("Elapsed (ms)", 0.001, disabled=True)
33
34    cfg = np.array(robot.joint_var_cls(0).default_factory())
35
36    while True:
37        # Solve IK.
38        start_time = time.time()
39        base_pos, base_wxyz, cfg = pks.solve_ik_with_base(
40            robot=robot,
41            target_link_name=target_link_name,
42            target_position=np.array(ik_target.position),
43            target_wxyz=np.array(ik_target.wxyz),
44            fix_base_position=(False, False, True),  # Only free along xy plane.
45            fix_base_orientation=(True, True, False),  # Free along z-axis rotation.
46            prev_pos=base_frame.position,
47            prev_wxyz=base_frame.wxyz,
48            prev_cfg=cfg,
49        )
50
51        # Update timing handle.
52        elapsed_time = time.time() - start_time
53        timing_handle.value = 0.99 * timing_handle.value + 0.01 * (elapsed_time * 1000)
54
55        # Update visualizer.
56        urdf_vis.update_cfg(cfg)
57        base_frame.position = np.array(base_pos)
58        base_frame.wxyz = np.array(base_wxyz)
59
60
61if __name__ == "__main__":
62    main()