Phylliade / ikpy

An Inverse Kinematics library aiming performance and modularity
http://phylliade.github.io/ikpy
Apache License 2.0
695 stars 151 forks source link

Working with 2 decimal places - different results #141

Closed vitalibr closed 1 year ago

vitalibr commented 1 year ago

First thank you for this amazing library, it is being of great help.

I'm working on a simple interface to control the movements of a robotic arm. I'm using 2 decimal places for the X, Y and Z position of the TCP (Tool Center Point).

I observed strange behavior, log:

[0. 0. 0. 0. 0. 0. 0.]
J1=0.0000000, J2=0.0000000, J3=0.0000000, J4=0.0000000, J5=0.0000000, J6=0.0000000

Calculating IK for X=765.23, Y=1033.93, Z=7.5
[ 0.00000000e+00 -3.37363117e-06 -1.44808632e-06  8.91130203e-07
  3.72508265e-09  2.28940762e-05  3.72549793e-09]
J1=-0.0001933, J2=-0.0000830, J3=0.0000511, J4=0.0000002, J5=0.0013117, J6=0.0000002

Calculating IK for X=765.23, Y=1033.93, Z=7.51
[ 0.00000000e+00 -6.85780741e-07 -1.48808844e-06  8.19374404e-07
 -1.99444505e-05  2.29050590e-05  1.99668060e-05]
J1=-0.0000393, J2=-0.0000853, J3=0.0000469, J4=-0.0011427, J5=0.0013124, J6=0.0011440

Calculating IK for X=765.23, Y=1033.93, Z=7.5
[ 0.00000000e+00 -3.81553870e-06 -1.44977983e-06  8.29304194e-07
 -4.80391295e-05  2.30806746e-05  4.80615190e-05]
J1=-0.0002186, J2=-0.0000831, J3=0.0000475, J4=-0.0027524, J5=0.0013224, J6=0.0027537

the code:

import math
import ikpy.chain

_tcpX = 765.22899999
_tcpY = 1033.93
_tcpZ = 7.5070

mychain = ikpy.chain.Chain.from_urdf_file("urdf/robot.urdf", active_links_mask=[False, True, True, True, True, True, True])
target_position = [ _tcpX/1000, _tcpZ/1000, _tcpY/1000 ]
ik = mychain.inverse_kinematics(target_position)
factor = 1
print(ik)
print('J1={:.7f}, J2={:.7f}, J3={:.7f}, J4={:.7f}, J5={:.7f}, J6={:.7f}'.format(
    math.degrees(ik[1].item()*factor),
    math.degrees(ik[2].item()*factor),
    math.degrees(ik[3].item()*factor),
    math.degrees(ik[4].item()*factor),
    math.degrees(ik[5].item()*factor),
    math.degrees(ik[6].item()*factor)))

def calculate_ik(X, Y, Z):
    global ik
    print(f"Calculating IK for X={X}, Y={Y}, Z={Z}")
    old_position = ik.copy()
    target_orientation = [0, 0, 0]
    target_position = [ X/1000, Z/1000, Y/1000 ]
    ik = mychain.inverse_kinematics(target_position, target_orientation, orientation_mode="Y", initial_position=old_position)
    factor = 1
    print(ik)
    print('J1={:.7f}, J2={:.7f}, J3={:.7f}, J4={:.7f}, J5={:.7f}, J6={:.7f}'.format(
        math.degrees(ik[1].item()*factor),
        math.degrees(ik[2].item()*factor),
        math.degrees(ik[3].item()*factor),
        math.degrees(ik[4].item()*factor),
        math.degrees(ik[5].item()*factor),
        math.degrees(ik[6].item()*factor)))

calculate_ik(X=765.23, Y=1033.93, Z=7.5)

calculate_ik(X=765.23, Y=1033.93, Z=7.51)

calculate_ik(X=765.23, Y=1033.93, Z=7.5)

another thing is that I would like to have all joints with 0 degrees using only 2 decimal places in X, Y and Z, but I only get it when I use the following values:

_tcpX = 765.22899999
_tcpY = 1033.93
_tcpZ = 7.5070

shouldn't the result in degrees be the same when X, Y and Z are the same as the previous calculation? What is wrong? Or am I misunderstanding the concept?