Interbotix / interbotix_ros_arms

ROS packages for the InterbotiX X-series family of robotic arms and turrets
BSD 2-Clause "Simplified" License
48 stars 29 forks source link

Robot IK Troubles #14

Closed Carmjor closed 4 years ago

Carmjor commented 4 years ago

Hello. There was a similar closed issue found here: Planning EE post was not successful but I still had some questions, as I'm rather new to Robotics.

I have a PincherX 100 that I'm trying to use with a stereo camera for autonomous operation, which requires Inverse Kinematics. Like the original poster, I tried the MoveIt! Python interface, but ran into issues with the 'y' component, and am not able to use the implemented gui for this.

As such, I tried using the functions specified in this script ee_pose_components.py, specifically:

arm.set_ee_pose_components(x=a, y=b, z=c, roll=d, pitch=e)

which worked well enough, but some XYZ points only worked for specific pitch and roll values, and I was looking for something which would handle the pitch and roll for me and simply go to a desired Cartesian point if it was valid under the entire pitch and roll range.

Where should I look to for this? Is there anything else in the interbotix_sdk that would help, or would I have to use the MoveIt! C++ API?

swinterbotix commented 4 years ago

Hi @Carmjor,

Thanks for bringing this up! There are some subtle points here that I think would be beneficial even for others who come across these issues...

I have a PincherX 100 that I'm trying to use with a stereo camera for autonomous operation, which requires Inverse Kinematics. Like the original poster, I tried the MoveIt! Python interface, but ran into issues with the 'y' component, and am not able to use the implemented gui for this.

First off, the MoveIt Python Interface script is independent of the implemented gui. The MoveIt Python Interface script builds off MoveIt's Python API which uses MoveIt Commander. The implemented GUI however builds off a small C++ class that I wrote which in turn uses MoveIt's C++ API.

Now in robotics, there's a concept called 'degrees of freedom' or 'dof' for short. In our platforms, this corresponds to the number of joints in the whole robotic arm minus the gripper. Essentially, 'dof' corresponds to the number of joints the IK engine has to play with to get the end-effector to a desired pose. For the PincherX 100, this number is 4 - it has 1 'yaw' joint (at the waist) and 3 pitch joints (at the shoulder, elbow, and wrist_angle). As a result, the end-effector of the PincherX 100 can reach some end-effector poses but not all of them. For example, it cannot reach any pose that specifies a non-zero 'roll'. Similarly, if the 'y' component of an end-effector pose is specified, the 'yaw' component is automatically defined (a single 'yaw' joint can only do so much) and must be specified correctly if planning a pose in the implemented gui or the Python MoveIt interface script.

So to control the end-effector to a specific XYZ pose, it would be better to use the 'Plan Position' button in the implemented gui. This lets MoveIt know that you don't care what orientation the end-effector ends up in - as long as it reaches the correct XYZ position relative to the 'base_link' frame. Similarly, if using the Python MoveIt Commander API, you should use the set_position_target function instead of the set_pose_target. Otherwise, If you were using the set_pose_target function, you would have to define the roll, pitch, and yaw values yourself - if you don't, MoveIt will just assume you want the end-effector to go to a specific XYZ position while maintaining an orientation of 0 roll, 0 pitch, and 0 yaw. So if you were 'planning a pose' containing a non-zero 'y' with a '0' yaw, that would be physically impossible.

As such, I tried using the functions specified in this script ee_pose_components.py, specifically:

arm.set_ee_pose_components(x=a, y=b, z=c, roll=d, pitch=e)

which worked well enough, but some XYZ points only worked for specific pitch and roll values, and I was looking for something which would handle the pitch and roll for me and simply go to a desired Cartesian point if it was valid under the entire pitch and roll range.

The nice thing about the set_ee_pose_components function is that it automatically determines what the 'yaw' value should be based on what your 'y' value is. This is probably why you had some success using this function. However, if you specified 'roll' to anything non-zero, that would fail since it's physically impossible for that arm to achieve any 'non-zero' roll. Regarding the 'pitch' value, ideally you should have +/- 90 degrees to play with. However, the further away your 'x', 'y', or 'z' values are from 0, this range becomes greatly diminished - as now the end-effector can only achieve small variations in pitch while maintaining a desired XYZ position. That said, there is currently no Python function in the interbotix_sdk that will allow you to just specify a desired XYZ position. So either you must think about where your end-effector will spatially end up, and command a desired pitch that be achieved in that position, or you can use the set_position_target function from the MoveIt Commander Python API or the setPositionTarget function available from the MoveIt C++ API.

swinterbotix commented 4 years ago

Closing this issue due to no activity. Feel free to reopen whenever!