Inverse Kinematics with the base fixed

Would it be possible to use the IK tutorials and get the joint states for a point without having to move the base? When I run the IK, the base moves as well. I tried setting the velocity and the axis of the joint_base_translation to 0. But that did not work. Removing the joint leads to an error due to mismatch in size. How would I solve this? Thank you.

Hey @Shashank_Shiva, glad to hear you’re using the code from the IK Tutorial. The way to fix the base is to remove the joint_base_translation joint. It sounds like you’ve already tried this? Would you share the error you’re seeing? Could you link to your code?

Hey @bshah,

This is the error I get when I comment out the joint_base_translation part of the code.

Traceback (most recent call last): 
  File "final_inv.py", line 121, in <module> 
    q_mid = chain.inverse_kinematics(target_point, pretarget_orientation, orientation_mode='all', initial_position=q_init) 
  File "/home/hello-robot/anaconda3/envs/myenv/lib/python3.8/site-packages/ikpy/chain.py", line 151, in inverse_kinematics 
    return self.inverse_kinematics_frame(target=frame_target, orientation_mode=orientation_mode, no_position=no_position, **kwargs) 
  File "/home/hello-robot/anaconda3/envs/myenv/lib/python3.8/site-packages/ikpy/chain.py", line 177, in inverse_kinematics_frame 
    return ik.inverse_kinematic_optimization(self, target, starting_nodes_angles=initial_position, **kwargs) 
  File "/home/hello-robot/anaconda3/envs/myenv/lib/python3.8/site-packages/ikpy/inverse_kinematics.py", line 149, in inverse_kinematic_optimization 
    res = scipy.optimize.least_squares(optimize_total, chain.active_from_full(starting_nodes_angles), bounds=real_bounds) 
  File "/home/hello-robot/anaconda3/envs/myenv/lib/python3.8/site-packages/scipy/optimize/_lsq/least_squares.py", line 820, in least_squares 
    f0 = fun_wrapped(x0) 
  File "/home/hello-robot/anaconda3/envs/myenv/lib/python3.8/site-packages/scipy/optimize/_lsq/least_squares.py", line 815, in fun_wrapped 
    return np.atleast_1d(fun(x, *args, **kwargs)) 
  File "/home/hello-robot/anaconda3/envs/myenv/lib/python3.8/site-packages/ikpy/inverse_kinematics.py", line 102, in optimize_function 
    fk = optimize_basis(x) 
  File "/home/hello-robot/anaconda3/envs/myenv/lib/python3.8/site-packages/ikpy/inverse_kinematics.py", line 49, in optimize_basis 
    y = chain.active_to_full(x, starting_nodes_angles) 
  File "/home/hello-robot/anaconda3/envs/myenv/lib/python3.8/site-packages/ikpy/chain.py", line 337, in active_to_full 
    np.place(full_joints, self.active_links_mask, active_joints) 
  File "<__array_function__ internals>", line 180, in place 
  File "/home/hello-robot/anaconda3/envs/myenv/lib/python3.8/site-packages/numpy/lib/function_base.py", line 1953, in place 
    return _insert(arr, mask, vals) 
ValueError: place: mask and data must be the same size 

I did not add any link name or joint time to the removal list.
Link to the current code: inversekinematics/final_inv.py at main · shashankshiva8/inversekinematics · GitHub

Thank you

Thanks @Shashank_Shiva. So the ValueError exception alone isn’t clearly communicating what went wrong, but paired with the traceback, we can understand. Inside the IKPy library, there’s a call to Numpy’s np.place() method, where the the data is full_joints and the mask if self.active_links_mask. The exception says ValueError: mask and data must be the same size, or in other words, there’s a mismatch in array length between these two variables. The self.active_links_mask is actually available to us, and if we printed it out, we would see something like: [False, True, False, True, True, ...], where each entry corresponds to a joint in the URDF, and the boolean tells IKPy whether it needs to solve for that joint or not (i.e. active or not). By default, all fixed joints are inactive and all prismatic/revolute joints are active. The data variable full_joints is not known to us, but looking at the traceback again, it’s a good guess that it might be starting_nodes_angles which would come from the initial guess that we give IKPy’s optimizer.

On the line where we call inverse_kinematics(), we pass in an initial guess for the optimizer to begin solving from, called q_init.

q_init comes from the get_current_configuration() method and is actually an array where each entry corresponds to a joint we expect is in the URDF, and the float value is the position of the joint in its range.

Since get_current_configuration() was written for a URDF that contained the “joint_base_translation” joint, the array returned looks like [0.0, q_base, 0.0, q_lift, 0.0, q_arml, q_arml, q_arml, q_arml, q_yaw, 0.0, 0.0], where q_base is 0.0 because we want the optimizer to start solving from no base motion being required. By commenting out the code that adds “joint_base_translation”, we’ve introduced a mismatch in array sizes, which is why we saw that ValueError exception. Since we don’t need q_base, the solution is to return the configuration array without “joint_base_translation”: [0.0, 0.0, q_lift, 0.0, q_arml, q_arml, q_arml, q_arml, q_yaw, 0.0, 0.0].

@bshah That makes sense on why I am having the mismatch in arrays. I will work on the changing the get_configuration part and get back to you. Thank you.

1 Like