In the last post, I went through how to build an operational space controller. It was surprisingly easy after we’ve worked through all the other posts. But maybe that was a little too *easy* for you. Maybe you want to do something more interesting like implement more than one controller at the same time. In this post we’ll go through how to work inside the null space of a controller to implement several seperate controllers simultaneously without interference.

Buckle up.

**Null space forces**

The last example comprises the basics of operational space control; describe the system, calculate the system dynamics, transform desired forces from an operational space to the generalized coordinates, and build the control signal to cancel out the undesired system dynamics. Basic operational space control works quite well, but it is not uncommon to have several control goals at once; such as `move the end-effector to this position’ (primary goal), and `keep the elbow raised high’ (secondary goal) in the control of a robot arm.

If the operational space can also serve as generalized coordinates, i.e. if the system state specified in operational space constrains all of the degrees of freedom of the robot, then there is nothing that can be done without affecting the performance of the primary controller. In the case of controlling a two-link robot arm this is the case. The end-effector Cartesian space (chosen as the operational space) could also be a generalized coordinates system, because a specific position fully constrains the position of the arm.

But often when using operational space control for more complex robots this is not the case. In these situations, the forces controlled in operational space have fewer dimensions than the robot has degrees of freedom, and so it is possible to accomplish the primary goal in a number of ways. The null space of this primary controller is the region of state space where there is a redundancy of solutions; the system can move in a number of ways and still not affect the completion of the goals of the primary controller. An example of this is all the different configurations the elbow can be in while a person moves their hand in a straight line. In these situations, a secondary controller can be created to operate in the null space of the primary controller, and the full control signal sent to the system is a sum of the primary control signal and a filtered version of the secondary control signal. In this section the derivation of the null-space filter will be worked through for a system with only a primary and secondary controller, but note that the process can be applied iteratively for systems with further controllers.

The filtering of the secondary control signal means that the secondary controller’s goals will only be accomplished if it is possible to do so without affecting the performance of the first controller. In other words, the secondary controller must operate in the null space of the first controller. Denote the primary operational space control signal, e.g. the control signal defined in the previous post, as and the control signal from the secondary controller . Define the force to apply to the system

where is the pseudo-inverse of .

Examining the filtering term that was added,

it can be seen that the Jacobian transpose multiplied by its pseudo-inverse will be 1’s all along the diagonal, except in the null space. This means that is subtracted from itself everywhere that affects the operational space movement and is left to apply any arbitrary control signal in the null space of the primary controller.

Unfortunately, this initial set up does not adequately filter out the effects of forces that might be generated by the secondary controller. The Jacobian is defined as a relationship between the velocities of two spaces, and so operating in the null space defined by the Jacobian ensures that no *velocities* are applied in operational space, but the required filter must also prevent any *accelerations* from affecting movement in operational space. The standard Jacobian pseudo-inverse null space is a velocity null space, and so a filter built using it will allow forces affecting the system’s acceleration to still get through. What is required is a pseudo-inverse Jacobian defined to filter signals through an acceleration null space.

To acquire this acceleration filter, our control signal will be substituted into the equation for acceleration in the operational space, which, after cancelling out gravity effects with the control signal and removing the unmodeled dynamics, gives

Rewriting this to separate the secondary controller into its own term

it becomes clear that to not cause any unwanted movement in operational space the second term must be zero.

There is only one free term left in the second term, and that is the pseudo-inverse. There are numerous different pseudo-inverses that can be chosen for a given situation, and here what is required is to engineer a pseudo-inverse such that the term multiplying in the above operational space acceleration equation is guaranteed to go to zero.

this needs to be true for all , so it can be removed,

substituting in our inertia matrix for operational space, which defines

This specific Jacobian inverse was presented in this 1987 paper by Dr. Oussama Khatib and is called the `dynamically consistent generalized inverse’. Using this psuedo-inverse guarantees that any signal coming from the secondary controller will not affect movement in the primary controller’s operational space. Just as a side-note, the name ‘pseudo-inverse’ is a bit of misnomer here, since it doesn’t try to produce the identity when multiplied by the original Jacobian transpose, but hey. That’s what they’re calling it.

The null space filter cancels out the acceleration effects of forces in operational space from a signal that is being applied as part of the control system. But it can also be used to cancel out the effects of any unwanted signal that can be modeled. Given some undesirable force signal interfering with the system that can be effectively modeled, a null space filtering term can be implemented to cancel it out. The control signal in this case, with one primary operational space controller and a null space filter for the undesired force, looks like:

We did it! This will now allow a high-priority operational space controller to execute without interference from a secondary controller operating in its null space to complete it’s own set of goals (when possible).

Example:

Given a three link arm (revolute-revolute-revolute) operating in the plane, shown below:

this example will construct the control system for a primary controller controlling the end-effector and a secondary controller working to keep the arm near its joint angles’ default resting positions.

Let the system state be with default positions . The control signal of the secondary controller is the difference between the target state and the current system state

where is a gain term.

Let the centres of mass be

the Jacobians for the COMs are

The Jacobian for the end-effector of this three link arm is

where and .

Taking the control signal developed in Section~\ref{sec:exampleOS}

where was defined in the previous post, and is defined two posts ago, and and are gain terms, usually set such that , and adding in the null space control signal and filter gives

where is the dynamically consistent generalized inverse defined above, and is our null space signal!

**Conclusions**

It’s a lot of math, but when you start to get a feel for it what’s really awesome is that this is it. We’re describing the whole system, and so by working with these equations we can get a super effective controller. Which is pretty cool. Especially in relation to other possible controllers.

Alright! We’ve now worked through all the basic theory for operational space control, it is time to get some implementations going.

[…] in our system to operate inside the null space of the first controller. We’ve already worked through all the math for this, so it’s straightforward to […]

Hey! Just wanted to say thanks a lot. This is awesome!

Thanks! Glad you enjoyed it!

Your tutorials are amazing, I am a graduate student, studied all these things, even with that, your tutorials seems to add much more. Thanks, keep up the good work.

Thank you for the kind words, glad you found them useful! 🙂

Hi!

I don’t understand the difference between F_and F_full and with ddot{x} and ddot{ x_full}. could you explain me?

I agree with the general opinion. Your tutorials are fantastic! Greetings!

Hello! Glad you’re enjoying the tutorials!

Ah yes, the notation is definitely not great, but the idea was that F_x is the forces applied by the primary controller, and F_x_full is sum of the forces applied by the primary controller and the secondary controller (where the secondary controller operates in the null space of the primary controller). Does that help clarify?

yes it does ! thanks!

[…] like the one in this post, add in another dimension of the task involving the gripper, implement a null-space controller to keep the arm near resting joint angles as it tracks the target, and on and […]

The way you have written those crazy robot equations and mathematical concepts in plain english, so comprehensively, is awesome. I have recently finished my PhD in robotics, but I still enjoy reading your blog. Thanks 🙂

Thank you for the very kind words! I really appreciate it. Cheers!

thanks 🙂

I am 71 years old. Since many years I am so much interested in robotics that I wasted about 25 years trying to make a real working controller in C++ .But it was vain and waste of time.

But your posts are very informative. Let me try to code. I will let you know the result.

Thanks, thanks a lot

akhan

Hello, glad to hear! Please keep me informed about how it goes! I’ll do my best to help whenever I can, too.

Cheers!

[…] base, we can replace those calculations with the following nice compact code (which also includes a secondary null-space controller to keep the arm near resting joint […]

[…] that you might notice about this is that it’s similar to the addition of the null space controller that we’ve seen before in operational space control. There’s a distinct difference here […]

Thanks for the tutorial. The Jacobians look wrong to me, shouldn’t all of the sin functions have a minus sign, and also in J2 shouldn’t the coefficient on the cos be 1/4 instead of 1/2?

If not, why?

Hi Saxman, you are totally right! Those are mistakes on my part, thanks for the catch!

Hi Travis, thank you for great tutorials. They are very helpful.

I just want to point to a broken link. The link to the “last post” is not working because it links to your admin page editing URL.

Hello! Glad you’ve found them useful, and thanks for the heads up! i’ll update it.

Hi Travis, thanks for the tutorial. I’m not following how you got J2. Specifically, it’s unclear to me how you got all of the “1/2” constants in the first row and all of the “1/4” constants in the third row when multiplying T(0,2) by COM2. When I do the matrix multiplication, I end up with both a 1/2 and a 1/4 in both rows.

Hi Ben,

What are you using for T(0, 2)?

When I just work out the math the end-effector position can be calculated as . When you take the derivative with respect to each of the joints gives you J2 the first 3 rows of J2, so I suspect that there might be an error in your T(0,2) matrix.

Hi Travis,

I’m sharing this Google Drive link to show my work. Hopefully these screenshots are legible enough.

https://docs.google.com/document/d/1Sd7Rk476PfVK0O_U6eRvL2P-jfwlDpAldfrK7NRmOAg/edit?usp=sharing

You can see that I arrived at a T(0,2)COM2 matrix that is nearly identical to yours, but I wasn’t able to simplify to that extent.

Just a quick update on this–I wrote my work up in Latex to make it easier to read.

https://docs.google.com/document/d/1Sd7Rk476PfVK0O_U6eRvL2P-jfwlDpAldfrK7NRmOAg/edit

Hi Ben! Sorry about the delay in replying, are you looking at the T(0, 2) from https://studywolf.wordpress.com/2013/08/21/robot-control-forward-transformation-matrices/ ? i’m just looking over that now and i think what you have is right and what i have on the page is incomplete … i’ll double check it today and update accordingly if it is wrong!

Hi Travis, glad I could (possibly) be of help. Any news on this? Btw, another question about this page: Here you have the gravity term g(q) as negative, whereas in the previous post it was positive, why is that?