# Inverse Kinematics Tutorial & Workshop Recording

**URL:** <https://forum.hello-robot.com/t/inverse-kinematics-tutorial-workshop-recording/639>\
**Category:** Knowledge Base\
**Created:** [March 19, 2023, 10:01am UTC](https://forum.hello-robot.com/t/inverse-kinematics-tutorial-workshop-recording/639 "2023-03-19T10:01:51Z")\
**Posts on this page:** 18\
**Page:** 1

<div class="post-metadata">

**Author:** ![bshah](https://yyz2.discourse-cdn.com/flex030/user_avatar/forum.hello-robot.com/bshah/32/55_2.png) [@bshah](https://forum.hello-robot.com/u/bshah)\
**Post date:** [March 19, 2023, 10:01am UTC](https://forum.hello-robot.com/t/inverse-kinematics-tutorial-workshop-recording/639/1 "2023-03-19T10:01:51Z")

</div>

[![Screenshot from 2023-03-19 02-23-01](https://canada1.discourse-cdn.com/flex030/uploads/hello_robot2/original/1X/60385076dbc0b54a42abfc2327ee66b6c9d26273.png)](https://github.com/hello-robot/stretch_tutorials/blob/master/stretch_body/jupyter/inverse_kinematics.ipynb)

New tutorial for inverse kinematics on Stretch has been [released on Github](https://github.com/hello-robot/stretch_tutorials/blob/master/stretch_body/jupyter/inverse_kinematics.ipynb)! You can preview the tutorial on Github, and instructions to run it are within the notebook itself.

Additionally, I’m hosting a workshop in 2 weeks to go through the tutorial and answer any questions. Here are the event details:

> # Inverse Kinematics Workshop
> 
> **Date:** March 29, 2023 at 11am PT  
> **Meeting Link** : [meet.google.com/yhm-ecbh-uof](http://meet.google.com/yhm-ecbh-uof)  
> **Agenda** : [Inverse Kinematics Workshop - Google Docs](https://docs.google.com/document/d/1mtFlcYvDELelepcE6QZ5oN85sC8zxgTvQlybsxGQa6g/edit?usp=sharing)

---

<div class="post-metadata">

**Author:** ![bshah](https://yyz2.discourse-cdn.com/flex030/user_avatar/forum.hello-robot.com/bshah/32/55_2.png) [@bshah](https://forum.hello-robot.com/u/bshah)\
**Post date:** [April 3, 2023, 10:03pm UTC](https://forum.hello-robot.com/t/inverse-kinematics-tutorial-workshop-recording/639/2 "2023-04-03T22:03:31Z")

</div>

Recording of the workshop is on Youtube at [Inverse Kinematics Workshop - Part 1 - YouTube](https://youtu.be/lfZRAdcHanU) !

[![](https://canada1.discourse-cdn.com/flex030/uploads/hello_robot2/original/1X/bcc914b3c50f4feb14af37a10099be36ba434d61.jpeg "Inverse Kinematics Workshop - Part 1") ](https://www.youtube.com/watch?v=lfZRAdcHanU)

---

<div class="post-metadata">

**Author:** ![arjung](https://yyz2.discourse-cdn.com/flex030/user_avatar/forum.hello-robot.com/arjung/32/410_2.png) [@arjung](https://forum.hello-robot.com/u/arjung)\
**Post date:** [April 10, 2023, 6:17am UTC](https://forum.hello-robot.com/t/inverse-kinematics-tutorial-workshop-recording/639/3 "2023-04-10T06:17:21Z")

</div>

Hi @bshah, thanks so much for this, this is extremely helpful! I was wondering – is there something similar for Forward Kinematics? I tried looking for a tutorial / python script for this, but had no luck. Thanks!

---

<div class="post-metadata">

**Author:** ![bshah](https://yyz2.discourse-cdn.com/flex030/user_avatar/forum.hello-robot.com/bshah/32/55_2.png) [@bshah](https://forum.hello-robot.com/u/bshah)\
**Post date:** [April 10, 2023, 6:34am UTC](https://forum.hello-robot.com/t/inverse-kinematics-tutorial-workshop-recording/639/4 "2023-04-10T06:34:50Z")

</div>

Hey @arjung, glad to hear you found it helpful! That’s a good question. The IK tutorial actually includes forward kinematics. Set everything up the same way as in the tutorial, and you can do FK using:

```auto
chain.forward_kinematics(q)

```

ROS has its own way of doing FK through a library called TF2. If you’re using ROS, check out this example:

> [@Rospy for tf and stretch\_body](https://forum.hello-robot.com/t/rospy-for-tf-and-stretch-body/565/6):
>
> Got it, below is an example that moves the arm to 0.5m while using tf at the same time to output the end effector position. However, I don’t use robot.arm.move\_to() in my example because it’s a Stretch Body method which will conflict with Stretch ROS. Instead, I use HelloNode.move\_to\_pose() which is part of Stretch ROS. If interested, I can explain why the difference matters. Before running the following, perform a git update on Stretch ROS using: roscd stretch\_core && git pull, and launch Stre…

---

<div class="post-metadata">

**Author:** ![Shashank\_Shiva](https://yyz2.discourse-cdn.com/flex030/user_avatar/forum.hello-robot.com/shashank_shiva/32/417_2.png) [@Shashank\_Shiva](https://forum.hello-robot.com/u/Shashank_Shiva)\
**Post date:** [April 17, 2023, 11:41pm UTC](https://forum.hello-robot.com/t/inverse-kinematics-tutorial-workshop-recording/639/5 "2023-04-17T23:41:48Z")

</div>

Hi Binit, I was able to execute the IK on the stretch and have it working. The mentioned goal point is respect to which origin? Thank you

---

<div class="post-metadata">

**Author:** ![Shashank\_Shiva](https://yyz2.discourse-cdn.com/flex030/user_avatar/forum.hello-robot.com/shashank_shiva/32/417_2.png) [@Shashank\_Shiva](https://forum.hello-robot.com/u/Shashank_Shiva)\
**Post date:** [April 17, 2023, 11:46pm UTC](https://forum.hello-robot.com/t/inverse-kinematics-tutorial-workshop-recording/639/6 "2023-04-17T23:46:05Z")

</div>

I missed the part that said the goal is defined with respect to base link. Thank you for the tutorial.

---

<div class="post-metadata">

**Author:** ![Shashank\_Shiva](https://yyz2.discourse-cdn.com/flex030/user_avatar/forum.hello-robot.com/shashank_shiva/32/417_2.png) [@Shashank\_Shiva](https://forum.hello-robot.com/u/Shashank_Shiva)\
**Post date:** [April 18, 2023, 12:08am UTC](https://forum.hello-robot.com/t/inverse-kinematics-tutorial-workshop-recording/639/7 "2023-04-18T00:08:04Z")

</div>

I have a question: If my goal pose is a 3D point in the optitrack world frame, how would I implement this?

---

<div class="post-metadata">

**Author:** ![bshah](https://yyz2.discourse-cdn.com/flex030/user_avatar/forum.hello-robot.com/bshah/32/55_2.png) [@bshah](https://forum.hello-robot.com/u/bshah)\
**Post date:** [April 18, 2023, 9:14am UTC](https://forum.hello-robot.com/t/inverse-kinematics-tutorial-workshop-recording/639/8 "2023-04-18T09:14:06Z")

</div>

Hi @Shashank_Shiva, would you open a new thread? I’d like to keep this thread focused on the IK tutorial.

Short answer: you’d need to transform the point into the robot’s frame, which requires you to also know where the robot’s frame is with respect to the optitrack world frame. You might do this by attaching fiducials to the robot, so optitrack can track where the robot is as well. Happy to elaborate in the new thread.

---

<div class="post-metadata">

**Author:** ![Shashank\_Shiva](https://yyz2.discourse-cdn.com/flex030/user_avatar/forum.hello-robot.com/shashank_shiva/32/417_2.png) [@Shashank\_Shiva](https://forum.hello-robot.com/u/Shashank_Shiva)\
**Post date:** [April 18, 2023, 10:04pm UTC](https://forum.hello-robot.com/t/inverse-kinematics-tutorial-workshop-recording/639/9 "2023-04-18T22:04:17Z")

</div>

I was able to transform the point. Thank you.

---

<div class="post-metadata">

**Author:** ![Shashank\_Shiva](https://yyz2.discourse-cdn.com/flex030/user_avatar/forum.hello-robot.com/shashank_shiva/32/417_2.png) [@Shashank\_Shiva](https://forum.hello-robot.com/u/Shashank_Shiva)\
**Post date:** [April 19, 2023, 2:30pm UTC](https://forum.hello-robot.com/t/inverse-kinematics-tutorial-workshop-recording/639/10 "2023-04-19T14:30:18Z")

</div>

@bshah I have created a new thread for IK with fixed base.

> [@Inverse Kinematics with the base fixed](https://forum.hello-robot.com/t/inverse-kinematics-with-the-base-fixed/677):
>
> 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.

---

<div class="post-metadata">

**Author:** ![Michal](https://avatars.discourse-cdn.com/v4/letter/m/34f0e0/32.png) [@Michal](https://forum.hello-robot.com/u/Michal)\
**Post date:** [July 5, 2023, 1:19pm UTC](https://forum.hello-robot.com/t/inverse-kinematics-tutorial-workshop-recording/639/11 "2023-07-05T13:19:03Z")

</div>

Hi, thank you for the helpful tutorial. I want to add the rotation of the base to this model and i did this with the following code. The joint tree seems to work but i want to make sure if i need to add any offsets in the joint\_base\_rotation in order for this to accurately represent the motion of the base.

```auto
joint_base_translation = urdfpy.Joint(name='joint_base_translation',
                                      parent='base_link',
                                      child='link_base_translation',
                                      joint_type='prismatic',
                                      axis=np.array([1.0, 0.0, 0.0]),
                                      origin=np.eye(4, dtype=np.float64),
                                      limit=urdfpy.JointLimit(effort=100.0, velocity=1.0, lower=-1.0, upper=1.0))
modified_urdf._joints.append(joint_base_translation)
link_base_translation = urdfpy.Link(name='link_base_translation',
                                    inertial=None,
                                    visuals=None,
                                    collisions=None)
modified_urdf._links.append(link_base_translation)
for j in modified_urdf._joints:
    if j.name == 'joint_mast':
        j.parent = 'link_base_translation'
joint_base_rotation = urdfpy.Joint(name='joint_base_rotation',
                                      parent='base_link',
                                      child='link_base_rotation',
                                      joint_type='revolute',
                                      axis=np.array([0.0, 0.0, 1.0]),
                                      origin=np.eye(4, dtype=np.float64),
                                      limit=urdfpy.JointLimit(effort=100.0, velocity=1.0, lower=-3.14, upper=3.14))
modified_urdf._joints.append(joint_base_rotation)
link_base_rotation = urdfpy.Link(name='link_base_rotation',
                                    inertial=None,
                                    visuals=None,
                                    collisions=None)
modified_urdf._links.append(link_base_rotation)

# amend the chain
for j in modified_urdf._joints:
    if j.name == 'joint_base_translation':
        j.parent = 'link_base_rotation'
print(f"name: {modified_urdf.name}")
print(f"num links: {len(modified_urdf.links)}")
print(f"num joints: {len(modified_urdf.joints)}")

```

---

<div class="post-metadata">

**Author:** ![bshah](https://yyz2.discourse-cdn.com/flex030/user_avatar/forum.hello-robot.com/bshah/32/55_2.png) [@bshah](https://forum.hello-robot.com/u/bshah)\
**Post date:** [July 6, 2023, 7:48pm UTC](https://forum.hello-robot.com/t/inverse-kinematics-tutorial-workshop-recording/639/12 "2023-07-06T19:48:27Z")

</div>

Hi @Michal, I haven’t run your code, but I believe the joint tree would cause errors since there is a loop. The tree would be:

 ![20230706_124347](https://canada1.discourse-cdn.com/flex030/uploads/hello_robot2/original/1X/ced665693306d6c577b9ce727deebf75cabf3963.jpeg)

This wouldn’t work since `joint_base_translation` has two parents.

---

<div class="post-metadata">

**Author:** ![Michal](https://avatars.discourse-cdn.com/v4/letter/m/34f0e0/32.png) [@Michal](https://forum.hello-robot.com/u/Michal)\
**Post date:** [July 7, 2023, 9:39am UTC](https://forum.hello-robot.com/t/inverse-kinematics-tutorial-workshop-recording/639/13 "2023-07-07T09:39:41Z")

</div>

The tree actually works and the inverse kinematics runs. But i cannot get the base to rotate with the command robot.base.rotate\_by(q\_base\_rotate). I can see that the inverse kinematics solves for a base rotation but this command doesnt result in any movement. All of the other joints run fine. Is there a way i can troubleshoot this?

 ![tree](https://canada1.discourse-cdn.com/flex030/uploads/hello_robot2/original/1X/7b23854dd18de96730f128a3cd212a669c81e57d.png)

---

<div class="post-metadata">

**Author:** ![bshah](https://yyz2.discourse-cdn.com/flex030/user_avatar/forum.hello-robot.com/bshah/32/55_2.png) [@bshah](https://forum.hello-robot.com/u/bshah)\
**Post date:** [July 9, 2023, 5:29am UTC](https://forum.hello-robot.com/t/inverse-kinematics-tutorial-workshop-recording/639/14 "2023-07-09T05:29:27Z")

</div>

I’d suggest troubleshooting this by printing out the solution that IKPy comes up with and visualizing it in Matplotlib as done in the notebook. Printing out the solution would help you determine if the rotation/translation are zero, in which case it would make sense that the robot doesn’t move. Visualizing the solution would help you determine if IKPy is actually able to converge, or if it is just timing out and returning the closest it can find. For example, the image below visualizes a solution that has converged to achieve the target point:

 ![image](https://canada1.discourse-cdn.com/flex030/uploads/hello_robot2/original/1X/bea854f51c1f46d73277705d63f7623c1ee59135.jpeg)

One thing I’ll note is that I wouldn’t expect a virtual base rotation joint followed by a virtual translation joint to model a differential drive base well. For example, that configuration couldn’t model a solution where the base has translated forward and than rotated in place. It might work for your use-case, but in my experience, throwing more dofs in the chain makes it harder for IKPy to find a solution.

---

<div class="post-metadata">

**Author:** ![roboor](https://avatars.discourse-cdn.com/v4/letter/r/3bc359/32.png) [@roboor](https://forum.hello-robot.com/u/roboor)\
**Post date:** [July 11, 2023, 8:38am UTC](https://forum.hello-robot.com/t/inverse-kinematics-tutorial-workshop-recording/639/15 "2023-07-11T08:38:08Z")

</div>

Hi @bshah,

Thanks for the great tutorial! Are you planning to upload the recordings of the other workshops soon as well? I am sure the Aruco Path Planning workshop will be quite beneficial for my project. The time shift to Europe makes it quite hard to attend the workshops live unfortunately 😕

Thanks,  
Noor

---

<div class="post-metadata">

**Author:** ![bshah](https://yyz2.discourse-cdn.com/flex030/user_avatar/forum.hello-robot.com/bshah/32/55_2.png) [@bshah](https://forum.hello-robot.com/u/bshah)\
**Post date:** [July 13, 2023, 1:20am UTC](https://forum.hello-robot.com/t/inverse-kinematics-tutorial-workshop-recording/639/16 "2023-07-13T01:20:12Z")

</div>

Hi @roboor, thank you! Unfortunately, I won’t be able to upload the recording of the Reach to Aruco workshop series, as I’ve discovered that the audio was distorted and sections of video weren’t recorded by my screen recording software. However, it may be helpful to look at the code that was made publicly available as part of the workshop, on the [feature/reach\_to\_aruco branch](https://github.com/hello-robot/stretch_ros/tree/feature/reach_to_aruco) of the Stretch ROS repository.

We may revisit the Reach to Aruco workshop series again in the future if there’s interest. In the meanwhile, I’d recommend starting a discussion here on the forum about Aruco and path planning related problems. The resulting discussion would likely be beneficial to anyone working with Aruco markers!

---

<div class="post-metadata">

**Author:** ![Michal](https://avatars.discourse-cdn.com/v4/letter/m/34f0e0/32.png) [@Michal](https://forum.hello-robot.com/u/Michal)\
**Post date:** [July 14, 2023, 7:17am UTC](https://forum.hello-robot.com/t/inverse-kinematics-tutorial-workshop-recording/639/17 "2023-07-14T07:17:16Z")

</div>

I didn’t solve the problem with trying to expand this example but I think i understood why it is likely not possible in the way i was approaching it. In short, you can’t in general use inverse kinematics to solve for joints given ee position for a non-holonomic mobile manipulator like stretch because the measure of the traveled distance of each wheel is not sufficient to calculate the final position of the robot. The final position depends on the path taken and during the ik iterations this information is not taken into account. On the bright side you can still formulate a full body Jacobian to achieve transformation between velocities instead of positions. This is useful for task space control if you have a given trajectory you want to follow. Here are some resources if anyone is interested.

#### Resource on non-holonomic constraints in mobile robotics

> **[3%20ETH%20Lecture%20%20Mobile%20Robots%20Kinematics%20add%20ons%202021%20RS.pdf](https://ethz.ch/content/dam/ethz/special-interest/mavt/robotics-n-intelligent-systems/asl-dam/documents/lectures/autonomous_mobile_robots/spring-2021/3%20ETH%20Lecture%20%20Mobile%20Robots%20Kinematics%20add%20ons%202021%20RS.pdf)**
>
> 2.61 MB

#### Resource on formulating the full body jacobian for a mobile manipulator

> **[13.5. Mobile Manipulation – Modern Robotics](https://modernrobotics.northwestern.edu/nu-gm-book-resource/13-5-mobile-manipulation/#department)**

---

<div class="post-metadata">

**Author:** ![bshah](https://yyz2.discourse-cdn.com/flex030/user_avatar/forum.hello-robot.com/bshah/32/55_2.png) [@bshah](https://forum.hello-robot.com/u/bshah)\
**Post date:** [July 14, 2023, 8:23am UTC](https://forum.hello-robot.com/t/inverse-kinematics-tutorial-workshop-recording/639/18 "2023-07-14T08:23:51Z")

</div>

Thanks @Michal! In the past, I haven’t had a good way to explain why you can’t formulate position tracking IK for a differential drive. I found your explanation to be intuitive:

> “because the measure of the traveled distance of each wheel is not sufficient to calculate the final position of the robot”

Since the manipulator jacobian is a mapping between change in joint space to change in task space, it makes sense that it wouldn’t work if you can’t know the change in task space (i.e. final position of the robot) from the change in joint space (i.e. traveled distance by each wheel).

I also appreciate the resources you’ve linked to. You can indeed develop velocity tracking IK for a differential drive robot, or full mobile manipulator like Stretch, and calculate the trajectory that the robot will follow elsewhere. It’s also easier for a geometric planner to create an obstacle avoiding trajectory, than it is to add obstacle avoiding constraints to the IK formulation. As far as I know, the IKPy library used in this tutorial doesn’t support velocity tracking or adding nonkinematic constraints.
