.. Comment: this file is automatically generated by `update_example_docs.py`.
It should not be modified manually.
IK with Mimic Joints
==========================================
This is a simple test to ensure that mimic joints are handled correctly in the IK solver.
We procedurally generate a "zig-zag" chain of links with mimic joints, where:
* the first joint is driven directly,
* and the remaining joints are driven indirectly via mimic joints.
The multipliers alternate between -1 and 1, and the offsets are all 0.
All examples can be run by first cloning the PyRoki repository, which includes the ``pyroki_snippets`` implementation details.
.. code-block:: python
:linenos:
import time
import numpy as np
import pyroki as pk
import viser
from viser.extras import ViserUrdf
import pyroki_snippets as pks
def create_chain_xml(length: float = 0.2, num_chains: int = 5) -> str:
def create_link(idx):
return f"""
"""
def create_joint(idx, multiplier=1.0, offset=0.0):
mimic = f''
return f"""
{mimic if idx != 0 else ""}
"""
world_joint_origin_z = length / 2.0
xml = f"""
"""
# Create the definition + first link.
xml += create_link(0)
xml += create_link(1)
xml += create_joint(0)
# Procedurally add more links.
assert num_chains >= 2
for idx in range(2, num_chains):
xml += create_link(idx)
current_offset = 0.0
current_multiplier = 1.0 * ((-1) ** (idx % 2))
xml += create_joint(idx - 1, current_multiplier, current_offset)
xml += """
"""
return xml
def main():
"""Main function for basic IK."""
import yourdfpy
import tempfile
xml = create_chain_xml(num_chains=10, length=0.1)
with tempfile.NamedTemporaryFile(mode="w", suffix=".urdf") as f:
f.write(xml)
f.flush()
urdf = yourdfpy.URDF.load(f.name)
# Create robot.
robot = pk.Robot.from_urdf(urdf)
# Set up visualizer.
server = viser.ViserServer()
server.scene.add_grid("/ground", width=2, height=2)
urdf_vis = ViserUrdf(server, urdf, root_node_name="/base")
target_link_name_handle = server.gui.add_dropdown(
"Target Link",
robot.links.names,
initial_value=robot.links.names[-1],
)
# Create interactive controller with initial position.
ik_target = server.scene.add_transform_controls(
"/ik_target", scale=0.2, position=(0.0, 0.1, 0.1), wxyz=(0, 0, 1, 0)
)
timing_handle = server.gui.add_number("Elapsed (ms)", 0.001, disabled=True)
while True:
# Solve IK.
start_time = time.time()
solution = pks.solve_ik(
robot=robot,
target_link_name=target_link_name_handle.value,
target_position=np.array(ik_target.position),
target_wxyz=np.array(ik_target.wxyz),
)
# Update timing handle.
elapsed_time = time.time() - start_time
timing_handle.value = 0.99 * timing_handle.value + 0.01 * (elapsed_time * 1000)
# Update visualizer.
urdf_vis.update_cfg(solution)
if __name__ == "__main__":
main()