copapy/tests/test_rev_kinematics.py

50 lines
1.4 KiB
Python
Raw Normal View History

2025-12-06 14:14:31 +00:00
import copapy as cp
# Arm lengths
l1, l2 = 1.8, 2.0
# Target position
target = cp.vector([0.7, 0.7])
2025-12-06 14:14:31 +00:00
# Learning rate for iterative adjustment
alpha = 0.1
2025-12-06 17:09:25 +00:00
def forward_kinematics(theta1: cp.value[float] | float, theta2: cp.value[float] | float) -> tuple[cp.vector[float], cp.vector[float]]:
2025-12-06 14:14:31 +00:00
"""Return positions of joint and end-effector."""
joint = cp.vector([l1 * cp.cos(theta1), l1 * cp.sin(theta1)])
end_effector = joint + cp.vector([l2 * cp.cos(theta1 + theta2),
l2 * cp.sin(theta1 + theta2)])
return joint, end_effector
def test_two_arms():
target_vec = cp.vector(target)
2025-12-06 17:09:25 +00:00
theta = cp.vector([cp.value(0.0), cp.value(0.0)])
2025-12-06 14:14:31 +00:00
joint = cp.vector([0.0, 0.0])
effector = cp.vector([0.0, 0.0])
error = 0.0
# Iterative IK
for _ in range(48):
joint, effector = forward_kinematics(theta[0], theta[1])
error = ((target_vec - effector) ** 2).sum()
grad_vec = cp.grad(error, theta)
theta -= alpha * grad_vec
tg = cp.Target()
tg.compile(error, theta, joint)
tg.run()
print(f"Joint angles: {tg.read_value(theta)}")
print(f"Joint position: {tg.read_value(joint)}")
print(f"End-effector position: {tg.read_value(effector)}")
print(f"quadratic error = {tg.read_value(error)}")
2025-12-06 14:14:31 +00:00
2025-12-24 13:10:26 +00:00
assert tg.read_value(error) < 1e-6
2025-12-06 14:14:31 +00:00
if __name__ == '__main__':
test_two_arms()