Chapter 4: Task-Space (Operational-Space) Control
Lesson 1: Task-Space vs Joint-Space Control Goals
In this lesson we formalize the difference between joint-space control and task-space (operational-space) control goals for robot manipulators. Assuming familiarity with kinematics and dynamics, we express both viewpoints in precise mathematical terms, compare their induced error dynamics, and prepare the ground for full operational-space control in subsequent lessons. We also provide multi-language code snippets to implement basic joint-space and task-space control objectives for a simple planar manipulator.
1. Conceptual Overview of Configuration vs Task Space
Let \( \mathbf{q} \in \mathbb{R}^n \) denote the vector of joint coordinates (revolute or prismatic). The joint space is \( \mathcal{Q} = \mathbb{R}^n \) (or a subset due to limits). The task space (operational space) is a space of operational variables such as end-effector position and orientation:
\[ \mathbf{x} = f(\mathbf{q}) \in \mathcal{X} \subset \mathbb{R}^m, \quad m \leq 6, \]
where \( f : \mathcal{Q} \to \mathcal{X} \) is the forward kinematics map. We assume that students already know how to compute \( f \) and the geometric Jacobian \( \mathbf{J}(\mathbf{q}) = \frac{\partial f}{\partial \mathbf{q}} \).
A joint-space control goal is specified as a desired trajectory \( \mathbf{q}_d(t) \), and we ask that the controller makes the actual joints \( \mathbf{q}(t) \) follow \( \mathbf{q}_d(t) \). A task-space control goal is specified as a desired operational trajectory \( \mathbf{x}_d(t) \), and we ask that the end-effector pose \( \mathbf{x}(t) \) follows \( \mathbf{x}_d(t) \).
These goals are related but not identical, especially in redundant manipulators where many different \( \mathbf{q} \) configurations realize the same \( \mathbf{x} \). The diagram below shows the basic information flow.
flowchart TD
Qspace["Joint space: q in R^n"] --> FK["Forward kinematics f(q)"]
FK --> Xspace["Task space: x in R^m"]
JD["Joint-space goal: qd(t)"] --> JC["Joint-space controller"]
TD["Task-space goal: xd(t)"] --> TC["Task-space controller"]
JC --> Act["Actuators / torques"]
TC --> Map["Map task commands to joints \nusing J(q), J(q)^T or J(q)^+"]
Map --> Act
In this lesson we remain mostly at the kinematic level (positions and velocities) and use the dynamics model only as a black box for converting desired joint accelerations to torques, which will be exploited more fully in the next lesson.
2. Error Definitions in Joint and Task Space
For a given desired joint trajectory \( \mathbf{q}_d(t) \), define the joint-space tracking error:
\[ \mathbf{e}_q(t) = \mathbf{q}(t) - \mathbf{q}_d(t). \]
For a given desired task-space trajectory \( \mathbf{x}_d(t) \), define the task-space tracking error:
\[ \mathbf{e}_x(t) = \mathbf{x}(t) - \mathbf{x}_d(t) = f(\mathbf{q}(t)) - \mathbf{x}_d(t). \]
A joint-space control objective is typically expressed as
\[ \lim_{t \to \infty} \mathbf{e}_q(t) = \mathbf{0}, \]
whereas a task-space control objective is
\[ \lim_{t \to \infty} \mathbf{e}_x(t) = \mathbf{0}. \]
Even if \( \mathbf{x}_d(t) = f(\mathbf{q}_d(t)) \), a controller that guarantees \( \mathbf{e}_q(t) \to 0 \) and one that guarantees \( \mathbf{e}_x(t) \to 0 \) can induce very different closed-loop properties (e.g., internal motions in redundant DOFs, behavior near singularities, manipulability).
For small deviations around a nominal configuration \( \mathbf{q}^\star \), linearization yields
\[ \delta \mathbf{x} \approx \mathbf{J}(\mathbf{q}^\star)\,\delta \mathbf{q}, \quad \delta \mathbf{q} = \mathbf{q} - \mathbf{q}^\star, \; \delta \mathbf{x} = \mathbf{x} - f(\mathbf{q}^\star). \]
Thus locally, joint-space and task-space errors are related by the Jacobian. Near a configuration where \( \mathbf{J}(\mathbf{q}^\star) \) has full row rank, the mapping from \( \delta \mathbf{x} \) to \( \delta \mathbf{q} \) is locally invertible.
3. Local Equivalence via Jacobian and Pseudoinverse
Assume a constant desired task-space point \( \mathbf{x}_d \). The purely kinematic motion of the robot is described by
\[ \dot{\mathbf{x}} = \mathbf{J}(\mathbf{q})\,\dot{\mathbf{q}}. \]
Define the task-space error \( \mathbf{e}_x = \mathbf{x} - \mathbf{x}_d \). Consider the following task-space velocity control law in joint space:
\[ \dot{\mathbf{q}} = - \mathbf{J}^+(\mathbf{q}) \, \mathbf{K}_x \, \mathbf{e}_x, \]
where \( \mathbf{J}^+(\mathbf{q}) \) is the (Moore–Penrose) pseudoinverse of the Jacobian and \( \mathbf{K}_x \in \mathbb{R}^{m \times m} \) is positive definite.
Proposition (Local task-space convergence). Suppose that in a neighborhood of the goal configuration, the Jacobian \( \mathbf{J}(\mathbf{q}) \) has full row rank \( m \) with \( m \leq n \). Then the above control law yields local exponential convergence of \( \mathbf{e}_x \).
Proof. Using the kinematics and the control law,
\[ \dot{\mathbf{e}}_x = \dot{\mathbf{x}} = \mathbf{J}(\mathbf{q})\,\dot{\mathbf{q}} = -\mathbf{J}(\mathbf{q}) \mathbf{J}^+(\mathbf{q}) \mathbf{K}_x \mathbf{e}_x. \]
For full row rank, \( \mathbf{J}(\mathbf{q}) \mathbf{J}^+(\mathbf{q}) = \mathbf{I}_m \), the identity on task space. Hence
\[ \dot{\mathbf{e}}_x = - \mathbf{K}_x \mathbf{e}_x. \]
Since \( \mathbf{K}_x \) is positive definite, this linear time-invariant system is exponentially stable; therefore \( \mathbf{e}_x(t) \to \mathbf{0} \) as \( t \to \infty \). Locality comes from the assumption that rank is preserved only near the goal. \(\square\)
The same controller expressed in joint space has the objective induced by the task-space goal; the state we directly specify is \( \mathbf{e}_x \), but the actual command is \( \dot{\mathbf{q}} \). This is fundamentally different from a controller that specifies the error \( \mathbf{e}_q \) as the primary objective.
4. Cost Functions and Gradients in Joint vs Task Space
A natural control design viewpoint is to minimize an instantaneous or integral cost functional. For example, a quadratic joint-space cost is
\[ \ell_q(\mathbf{q}) = \tfrac{1}{2} (\mathbf{q} - \mathbf{q}_d)^\top \mathbf{W}_q (\mathbf{q} - \mathbf{q}_d), \]
where \( \mathbf{W}_q \succ 0 \) is a weighting matrix. The gradient with respect to joints is
\[ \nabla_{\mathbf{q}} \ell_q = \mathbf{W}_q (\mathbf{q} - \mathbf{q}_d) = \mathbf{W}_q \mathbf{e}_q. \]
A quadratic task-space cost is instead
\[ \ell_x(\mathbf{q}) = \tfrac{1}{2} (f(\mathbf{q}) - \mathbf{x}_d)^\top \mathbf{W}_x (f(\mathbf{q}) - \mathbf{x}_d) = \tfrac{1}{2} \mathbf{e}_x^\top \mathbf{W}_x \mathbf{e}_x. \]
Using the chain rule, the gradient with respect to joints is
\[ \nabla_{\mathbf{q}} \ell_x = \mathbf{J}(\mathbf{q})^\top \mathbf{W}_x \mathbf{e}_x. \]
This explains the ubiquitous appearance of \( \mathbf{J}(\mathbf{q})^\top \mathbf{e}_x \) terms in many task-space controllers: it is the steepest descent direction in joint space for a cost that is defined in task space.
In contrast, a joint-space controller that directly minimizes \( \ell_q \) ignores the task-space geometry encoded by \( \mathbf{J}(\mathbf{q}) \). Consequently, it may achieve perfect joint tracking while exhibiting poor behavior in task space (e.g., low manipulability, large forces, or joint limit issues).
5. Kinematic Control Laws (Joint vs Task Space)
At the kinematic level, we can define simple proportional controllers on velocities. For joint space:
\[ \dot{\mathbf{q}} = \dot{\mathbf{q}}_d - \mathbf{K}_q \mathbf{e}_q, \]
where \( \mathbf{K}_q \succ 0 \). For task space, a natural analog is:
\[ \dot{\mathbf{q}} = \dot{\mathbf{q}}_0 - \mathbf{J}^+(\mathbf{q}) \mathbf{K}_x \mathbf{e}_x, \]
where \( \dot{\mathbf{q}}_0 \) is some nominal joint motion (e.g., for secondary objectives) and \( \mathbf{K}_x \succ 0 \). If we choose \( \dot{\mathbf{q}}_0 = \mathbf{0} \), we obtain the controller of Section 3. In later lessons we will embed such velocity-level laws inside a full dynamic controller (e.g., operational-space inverse dynamics).
At the torque level, one often uses inverse-dynamics based controllers, where a desired joint acceleration \( \ddot{\mathbf{q}}_{\text{des}} \) coming from either a joint-space or task-space objective is mapped to joint torques via the known dynamics:
\[ \tau = \mathbf{M}(\mathbf{q}) \ddot{\mathbf{q}}_{\text{des}} + \mathbf{C}(\mathbf{q}, \dot{\mathbf{q}}) \dot{\mathbf{q}} + \mathbf{g}(\mathbf{q}), \]
where \( \mathbf{M} \) is the inertia matrix, \( \mathbf{C} \) the Coriolis/centrifugal term, and \( \mathbf{g} \) the gravity vector. The difference between joint-space and task-space control lies in how \( \ddot{\mathbf{q}}_{\text{des}} \) is designed.
6. Example — Planar 2-DOF Arm Kinematics
Consider a planar 2-DOF manipulator with link lengths \( l_1, l_2 > 0 \) and joint angles \( \mathbf{q} = [q_1, q_2]^\top \). The end-effector position in Cartesian coordinates \( \mathbf{x} = [x, y]^\top \) is
\[ x = l_1 \cos q_1 + l_2 \cos(q_1 + q_2), \quad y = l_1 \sin q_1 + l_2 \sin(q_1 + q_2). \]
The Jacobian \( \mathbf{J}(\mathbf{q}) \in \mathbb{R}^{2 \times 2} \) is
\[ \mathbf{J}(\mathbf{q}) = \begin{bmatrix} -l_1 \sin q_1 - l_2 \sin(q_1 + q_2) & -l_2 \sin(q_1 + q_2) \\ l_1 \cos q_1 + l_2 \cos(q_1 + q_2) & l_2 \cos(q_1 + q_2) \end{bmatrix}. \]
For this arm, \( \det \mathbf{J}(\mathbf{q}) = l_1 l_2 \sin q_2 \). Hence the configuration is singular iff \( \sin q_2 = 0 \), i.e., when the arm is fully stretched or folded (elbow straight). Near non-singular configurations, joint-space and task-space control objectives are smoothly related; near singularities, attempting to achieve some task-space goals may require extremely large joint motions or torques.
7. Python Implementation — Joint vs Task-Space Goals
We now implement joint-space and task-space kinematic controllers for the planar 2-DOF arm. We assume an external low-level torque controller or inverse-dynamics function to map desired accelerations to torques. The focus here is on goal specification and kinematic mapping.
import numpy as np
# Planar 2-DOF forward kinematics and Jacobian
def fk_planar_2dof(q, l1=1.0, l2=1.0):
q1, q2 = q
x = l1 * np.cos(q1) + l2 * np.cos(q1 + q2)
y = l1 * np.sin(q1) + l2 * np.sin(q1 + q2)
return np.array([x, y])
def jac_planar_2dof(q, l1=1.0, l2=1.0):
q1, q2 = q
J = np.zeros((2, 2))
J[0, 0] = -l1 * np.sin(q1) - l2 * np.sin(q1 + q2)
J[0, 1] = -l2 * np.sin(q1 + q2)
J[1, 0] = l1 * np.cos(q1) + l2 * np.cos(q1 + q2)
J[1, 1] = l2 * np.cos(q1 + q2)
return J
# Placeholder for an inverse-dynamics function from previous lessons
def inverse_dynamics(q, qd, qdd_des):
"""
Map desired joint accelerations qdd_des to torques tau using
the known robot dynamics M(q), C(q, qd), g(q).
Here we just return qdd_des as a stand-in.
"""
return qdd_des
def joint_space_pd(q, qd, q_des, qd_des, Kp, Kd):
e_q = q_des - q
e_qd = qd_des - qd
qdd_des = Kp @ e_q + Kd @ e_qd
tau = inverse_dynamics(q, qd, qdd_des)
return tau
def task_space_pd(q, qd, x_des, xd_des, Kx, D_x, l1=1.0, l2=1.0):
# Current task state
x = fk_planar_2dof(q, l1, l2)
J = jac_planar_2dof(q, l1, l2)
# Task-space velocity
xdot = J @ qd
# Task-space errors
e_x = x_des - x
e_xd = xd_des - xdot
# Desired task-space acceleration (simple PD)
xdd_des = Kx @ e_x + D_x @ e_xd
# Map task acceleration to joint acceleration (pseudoinverse)
J_pinv = np.linalg.pinv(J)
qdd_des = J_pinv @ xdd_des
tau = inverse_dynamics(q, qd, qdd_des)
return tau
if __name__ == "__main__":
# Example usage
q = np.array([0.4, 0.2])
qd = np.array([0.0, 0.0])
q_des = np.array([0.5, 0.3])
qd_des = np.array([0.0, 0.0])
x_des = fk_planar_2dof(q_des) # consistent with q_des
xd_des = np.array([0.0, 0.0])
Kp = np.diag([30.0, 30.0])
Kd = np.diag([10.0, 10.0])
Kx = np.diag([50.0, 50.0])
Dx = np.diag([20.0, 20.0])
tau_joint = joint_space_pd(q, qd, q_des, qd_des, Kp, Kd)
tau_task = task_space_pd(q, qd, x_des, xd_des, Kx, Dx)
print("Tau (joint-space goal) =", tau_joint)
print("Tau (task-space goal) =", tau_task)
In practice, inverse_dynamics would use the exact dynamics
derived in prior lessons. Note that even when
x_des = fk_planar_2dof(q_des), the joint torques computed
by joint-space and task-space controllers differ, leading to different
transient behaviors.
8. C++ Implementation with Eigen
A C++ skeleton using Eigen for vectors and matrices. This code emphasizes how joint-space vs task-space goals enter the computation of desired accelerations.
#include <iostream>
#include <Eigen/Dense>
using Eigen::Vector2d;
using Eigen::Matrix2d;
struct Planar2DOF {
double l1{1.0};
double l2{1.0};
Vector2d fk(const Vector2d& q) const {
double q1 = q(0), q2 = q(1);
double x = l1 * std::cos(q1) + l2 * std::cos(q1 + q2);
double y = l1 * std::sin(q1) + l2 * std::sin(q1 + q2);
return Vector2d(x, y);
}
Matrix2d jacobian(const Vector2d& q) const {
double q1 = q(0), q2 = q(1);
Matrix2d J;
J(0,0) = -l1 * std::sin(q1) - l2 * std::sin(q1 + q2);
J(0,1) = -l2 * std::sin(q1 + q2);
J(1,0) = l1 * std::cos(q1) + l2 * std::cos(q1 + q2);
J(1,1) = l2 * std::cos(q1 + q2);
return J;
}
};
// Placeholder inverse dynamics (should be replaced by real dynamics)
Vector2d inverseDynamics(const Vector2d& q,
const Vector2d& qd,
const Vector2d& qdd_des)
{
return qdd_des; // stand-in for tau
}
Vector2d jointSpacePD(const Vector2d& q,
const Vector2d& qd,
const Vector2d& q_des,
const Vector2d& qd_des,
const Matrix2d& Kp,
const Matrix2d& Kd)
{
Vector2d e_q = q_des - q;
Vector2d e_qd = qd_des - qd;
Vector2d qdd_des = Kp * e_q + Kd * e_qd;
return inverseDynamics(q, qd, qdd_des);
}
Vector2d taskSpacePD(const Planar2DOF& arm,
const Vector2d& q,
const Vector2d& qd,
const Vector2d& x_des,
const Vector2d& xd_des,
const Matrix2d& Kx,
const Matrix2d& Dx)
{
Vector2d x = arm.fk(q);
Matrix2d J = arm.jacobian(q);
Vector2d xdot = J * qd;
Vector2d e_x = x_des - x;
Vector2d e_xd = xd_des - xdot;
Vector2d xdd_des = Kx * e_x + Dx * e_xd;
// Pseudoinverse of 2x2 matrix (non-singular assumption)
Matrix2d Jinv = J.inverse();
Vector2d qdd_des = Jinv * xdd_des;
return inverseDynamics(q, qd, qdd_des);
}
int main() {
Planar2DOF arm;
Vector2d q(0.4, 0.2);
Vector2d qd(0.0, 0.0);
Vector2d q_des(0.5, 0.3);
Vector2d qd_des(0.0, 0.0);
Vector2d x_des = arm.fk(q_des);
Vector2d xd_des(0.0, 0.0);
Matrix2d Kp = Matrix2d::Identity() * 30.0;
Matrix2d Kd = Matrix2d::Identity() * 10.0;
Matrix2d Kx = Matrix2d::Identity() * 50.0;
Matrix2d Dx = Matrix2d::Identity() * 20.0;
Vector2d tau_joint = jointSpacePD(q, qd, q_des, qd_des, Kp, Kd);
Vector2d tau_task = taskSpacePD(arm, q, qd, x_des, xd_des, Kx, Dx);
std::cout << "Tau (joint-space): " << tau_joint.transpose() << std::endl;
std::cout << "Tau (task-space): " << tau_task.transpose() << std::endl;
return 0;
}
In a more advanced implementation, inverseDynamics would be
replaced by a function using the full manipulator dynamics, and the
Jacobian inverse would be replaced by a numerically robust pseudoinverse
that handles near singularities.
9. Java Implementation (EJML for Linear Algebra)
Java does not have a de facto standard robotics library, but the EJML library provides efficient dense linear algebra that can be used to implement kinematics and task-space control. Below is a minimal example (omitting package and import lines for brevity).
public class Planar2DOF {
public double l1 = 1.0;
public double l2 = 1.0;
public double[] fk(double[] q) {
double q1 = q[0];
double q2 = q[1];
double x = l1 * Math.cos(q1) + l2 * Math.cos(q1 + q2);
double y = l1 * Math.sin(q1) + l2 * Math.sin(q1 + q2);
return new double[]{x, y};
}
public double[][] jacobian(double[] q) {
double q1 = q[0];
double q2 = q[1];
double[][] J = new double[2][2];
J[0][0] = -l1 * Math.sin(q1) - l2 * Math.sin(q1 + q2);
J[0][1] = -l2 * Math.sin(q1 + q2);
J[1][0] = l1 * Math.cos(q1) + l2 * Math.cos(q1 + q2);
J[1][1] = l2 * Math.cos(q1 + q2);
return J;
}
}
// Skeleton controller using EJML SimpleMatrix
// (Assume: import org.ejml.simple.SimpleMatrix;)
public class Controllers {
public static SimpleMatrix inverseDynamics(SimpleMatrix q,
SimpleMatrix qd,
SimpleMatrix qddDes) {
// Placeholder: in a real implementation, use M(q), C(q, qd), g(q)
return qddDes;
}
public static SimpleMatrix jointSpacePD(SimpleMatrix q,
SimpleMatrix qd,
SimpleMatrix qDes,
SimpleMatrix qdDes,
SimpleMatrix Kp,
SimpleMatrix Kd) {
SimpleMatrix eQ = qDes.minus(q);
SimpleMatrix eQd = qdDes.minus(qd);
SimpleMatrix qddDes = Kp.mult(eQ).plus(Kd.mult(eQd));
return inverseDynamics(q, qd, qddDes);
}
public static SimpleMatrix taskSpacePD(Planar2DOF arm,
SimpleMatrix q,
SimpleMatrix qd,
SimpleMatrix xDes,
SimpleMatrix xdDes,
SimpleMatrix Kx,
SimpleMatrix Dx) {
double[] qArr = new double[]{q.get(0), q.get(1)};
double[] xArr = arm.fk(qArr);
double[][] JArr = arm.jacobian(qArr);
SimpleMatrix x = new SimpleMatrix(2, 1, true, xArr);
SimpleMatrix J = new SimpleMatrix(2, 2, true,
JArr[0][0], JArr[0][1],
JArr[1][0], JArr[1][1]);
SimpleMatrix xdot = J.mult(qd);
SimpleMatrix eX = xDes.minus(x);
SimpleMatrix eXd = xdDes.minus(xdot);
SimpleMatrix xddDes = Kx.mult(eX).plus(Dx.mult(eXd));
// Pseudoinverse for 2x2 (non-singular assumption)
SimpleMatrix Jinv = J.invert();
SimpleMatrix qddDes = Jinv.mult(xddDes);
return inverseDynamics(q, qd, qddDes);
}
}
Here the distinction between joint-space and task-space goals is encoded
in whether the controller uses qDes or xDes as
the primary reference and whether the Jacobian appears explicitly.
10. MATLAB / Simulink Implementation
In MATLAB, we can implement the same 2-DOF arm controllers, and in Simulink these functions can be wrapped in blocks connected to a plant model and integrators.
function tau = joint_space_pd(q, qd, q_des, qd_des, Kp, Kd)
% q, qd, q_des, qd_des: 2x1 vectors
e_q = q_des - q;
e_qd = qd_des - qd;
qdd_des = Kp * e_q + Kd * e_qd;
tau = inverse_dynamics(q, qd, qdd_des);
end
function tau = task_space_pd(q, qd, x_des, xd_des, Kx, Dx, l1, l2)
if nargin < 7
l1 = 1.0; l2 = 1.0;
end
[x, J] = fk_and_jac_planar_2dof(q, l1, l2);
xdot = J * qd;
e_x = x_des - x;
e_xd = xd_des - xdot;
xdd_des = Kx * e_x + Dx * e_xd;
% Pseudoinverse (non-singular assumption)
qdd_des = pinv(J) * xdd_des;
tau = inverse_dynamics(q, qd, qdd_des);
end
function [x, J] = fk_and_jac_planar_2dof(q, l1, l2)
q1 = q(1); q2 = q(2);
x = [ l1*cos(q1) + l2*cos(q1+q2);
l1*sin(q1) + l2*sin(q1+q2) ];
J = [ -l1*sin(q1) - l2*sin(q1+q2), -l2*sin(q1+q2);
l1*cos(q1) + l2*cos(q1+q2), l2*cos(q1+q2) ];
end
function tau = inverse_dynamics(q, qd, qdd_des)
% Placeholder for full dynamic model
tau = qdd_des;
end
In Simulink, one can create two subsystems: a joint-space controller and a task-space controller. Both output desired joint accelerations, which are fed into an inverse-dynamics block (e.g., implemented using the Robotics System Toolbox or a custom S-function) and then to a plant model of the manipulator.
11. Wolfram Mathematica — Symbolic View of Jacobian Relationship
Wolfram Mathematica is well suited for symbolically deriving forward kinematics, Jacobians, and verifying relationships between joint and task-space errors.
(* Symbolic planar 2-DOF arm *)
Clear[q1, q2, l1, l2];
x[q1_, q2_] := l1 Cos[q1] + l2 Cos[q1 + q2];
y[q1_, q2_] := l1 Sin[q1] + l2 Sin[q1 + q2];
xVec[q1_, q2_] := {x[q1, q2], y[q1, q2]};
J = D[xVec[q1, q2], {{q1, q2}}]; (* 2x2 Jacobian *)
Simplify[J]
(* Local relation between small variations *)
dq = {Subscript[\[Delta], q1], Subscript[\[Delta], q2]};
dx = J . dq // Simplify
(* Define a quadratic task-space cost and compute gradient in joint space *)
Clear[xd1, xd2, Wx];
xd = {xd1, xd2};
ex = xVec[q1, q2] - xd;
Wx = { {w1, 0}, {0, w2} };
ellx = 1/2 ex . Wx . ex;
gradq = Grad[ellx, {q1, q2}] // Simplify
(* Show that gradq = J^T Wx ex *)
JT = Transpose[J];
rhs = JT . Wx . ex // Simplify;
Simplify[gradq - rhs]
The last Simplify call confirms that the gradient of a
quadratic cost in task space is
\( \nabla_{\mathbf{q}} \ell_x = \mathbf{J}(\mathbf{q})^\top
\mathbf{W}_x \mathbf{e}_x \), reinforcing the conceptual difference between joint-space and
task-space control goals.
12. Problems and Solutions
Problem 1 (Local relation between joint and task errors). For the planar 2-DOF arm, derive the first-order relation between small joint-space errors \( \delta \mathbf{q} \) and task-space errors \( \delta \mathbf{x} \), and show explicitly that \( \delta \mathbf{x} = \mathbf{J}(\mathbf{q}^\star)\,\delta \mathbf{q} \).
Solution. Let \( \mathbf{x} = f(\mathbf{q}) \). Take a nominal configuration \( \mathbf{q}^\star \) and apply a small perturbation \( \delta \mathbf{q} \). A first-order Taylor expansion gives
\[ \mathbf{x}(\mathbf{q}^\star + \delta \mathbf{q}) \approx \mathbf{x}(\mathbf{q}^\star) + \mathbf{J}(\mathbf{q}^\star)\,\delta \mathbf{q}, \]
where \( \mathbf{J}(\mathbf{q}^\star) = \frac{\partial f}{\partial \mathbf{q}} (\mathbf{q}^\star) \). Thus
\[ \delta \mathbf{x} := \mathbf{x}(\mathbf{q}^\star + \delta \mathbf{q}) - \mathbf{x}(\mathbf{q}^\star) \approx \mathbf{J}(\mathbf{q}^\star)\,\delta \mathbf{q}, \]
which is the desired relation. For the concrete formulas of Section 6, one can compute \( \mathbf{J}(\mathbf{q}) \) directly and verify that the partial derivatives match the general expression.
Problem 2 (Task-space velocity control stability). Consider the pure kinematic system \( \dot{\mathbf{x}} = \mathbf{J}(\mathbf{q})\,\dot{\mathbf{q}} \) with constant \( \mathbf{x}_d \). Assume \( \mathbf{J}(\mathbf{q}) \) has full row rank \( m \) in a neighborhood of the goal. Show that the control
\[ \dot{\mathbf{q}} = -\mathbf{J}^+(\mathbf{q}) \mathbf{K}_x \mathbf{e}_x \]
with \( \mathbf{K}_x \succ 0 \) yields \( \dot{\mathbf{e}}_x = -\mathbf{K}_x \mathbf{e}_x \) and conclude exponential convergence.
Solution. This has already been derived in Section 3; we collect the essential steps. Using the kinematics,
\[ \dot{\mathbf{e}}_x = \dot{\mathbf{x}} = \mathbf{J}(\mathbf{q})\,\dot{\mathbf{q}} = -\mathbf{J}(\mathbf{q})\,\mathbf{J}^+(\mathbf{q}) \mathbf{K}_x \mathbf{e}_x. \]
Full row rank implies \( \mathbf{J}(\mathbf{q})\,\mathbf{J}^+(\mathbf{q}) = \mathbf{I}_m \), so
\[ \dot{\mathbf{e}}_x = -\mathbf{K}_x \mathbf{e}_x. \]
The solution is \( \mathbf{e}_x(t) = \exp(-\mathbf{K}_x t)\,\mathbf{e}_x(0) \), which converges to zero exponentially because \( \mathbf{K}_x \succ 0 \).
Problem 3 (Difference between joint-space and task-space goals). For the planar 2-DOF arm with \( l_1 = l_2 = 1 \), consider the desired task-space point \( \mathbf{x}_d = [1, 1]^\top \). Find two different joint configurations \( \mathbf{q}^{(1)} \) and \( \mathbf{q}^{(2)} \) that realize the same \( \mathbf{x}_d \). Explain why a joint-space controller that drives \( \mathbf{q} \to \mathbf{q}^{(1)} \) and a task-space controller that drives \( \mathbf{x} \to \mathbf{x}_d \) may generate different internal motions.
Solution. The inverse kinematics for the 2-DOF planar arm yields two solutions (elbow-up and elbow-down) whenever the target is reachable. Solving \( \mathbf{x}_d = f(\mathbf{q}) \) produces \( \mathbf{q}^{(1)} = [q_1^{(1)}, q_2^{(1)}]^\top \) and \( \mathbf{q}^{(2)} = [q_1^{(2)}, q_2^{(2)}]^\top \) that map to the same \( \mathbf{x}_d \). A joint-space controller that takes \( \mathbf{q}_d = \mathbf{q}^{(1)} \) has the precise goal
\[ \lim_{t \to \infty} \mathbf{q}(t) = \mathbf{q}^{(1)}, \]
implying a specific elbow posture. A task-space controller with goal \( \mathbf{x}_d \) does not distinguish between the two IK branches; depending on initialization, it may converge to either configuration. This illustrates that task-space goals generally do not fix the internal (redundant) posture, which must be shaped by secondary objectives (e.g., joint limits, manipulability).
Problem 4 (Singularity and feasibility of task-space goals). For the planar arm, recall that \( \det \mathbf{J}(\mathbf{q}) = l_1 l_2 \sin q_2 \). Explain why, at a configuration with \( q_2 = 0 \), certain task-space velocity goals cannot be achieved with finite joint velocities even though the end-effector position may be far from workspace boundaries.
Solution. At \( q_2 = 0 \) the Jacobian loses rank (its determinant is zero). In that case, the mapping \( \dot{\mathbf{x}} = \mathbf{J}(\mathbf{q})\,\dot{\mathbf{q}} \) has a non-trivial null space and fails to be onto: not every task-space velocity \( \dot{\mathbf{x}} \) can be realized by some \( \dot{\mathbf{q}} \). Attempting to invert the Jacobian leads to arbitrarily large joint velocities, which is impractical. From a control viewpoint, a task-space controller that does not explicitly handle singularities may request infeasible or dangerously large joint motions near \( q_2 = 0 \), whereas a joint-space controller might remain well behaved but fail to track the desired task-space trajectory.
flowchart TD
S["Specify goal in joint space (qd) or task space (xd)"]
S --> JG["Joint-space: minimize eq = q - qd"]
S --> TG["Task-space: minimize ex = x - xd"]
JG --> M1["Internal posture fully specified \n(non-redundant)"]
TG --> M2["Internal posture underdetermined \n(redundant)"]
M2 --> SEC["Secondary objectives \n(limits, manipulability, etc.)"]
13. Summary
In this lesson we distinguished clearly between joint-space and task-space control goals. Joint-space control regulates the configuration variables \( \mathbf{q} \), while task-space control regulates operational variables \( \mathbf{x} = f(\mathbf{q}) \). We formalized the local relationship \( \delta \mathbf{x} = \mathbf{J}(\mathbf{q})\,\delta \mathbf{q} \), derived gradient expressions showing why \( \mathbf{J}^\top \) appears naturally in task-space control, and proved local convergence for a simple Jacobian pseudoinverse controller. Through multi-language implementations, we showed how the same plant model can be controlled using either joint or task-space goals, leading to different internal postures and behaviors, particularly in redundant and near-singular configurations. These concepts form the conceptual backbone for the full operational-space control formulation of the next lesson.
14. References
- Khatib, O. (1987). A unified approach for motion and force control of robot manipulators: The operational space formulation. IEEE Journal of Robotics and Automation, 3(1), 43–53.
- Yoshikawa, T. (1985). Manipulability of robotic mechanisms. International Journal of Robotics Research, 4(2), 3–9.
- Slotine, J.-J. E., & Li, W. (1987). On the adaptive control of robot manipulators. International Journal of Robotics Research, 6(3), 49–59.
- Hsu, P., Slotine, J.-J. E., & Sastry, S. S. (1988). Dynamic task-space control of robot manipulators: A Lyapunov approach. IEEE Transactions on Automatic Control, 33(5), 461–468.
- Sciavicco, L., & Siciliano, B. (1990). A solution algorithm to the inverse kinematic problem for redundant manipulators. IEEE Journal of Robotics and Automation, 4(4), 403–410.
- Nakamura, Y. (1991). Advanced robotics: Redundancy and optimization. Addison-Wesley, selected chapters.
- Chiaverini, S. (1997). Singularity-robust task-priority redundancy resolution for real-time kinematic control of robot manipulators. IEEE Transactions on Robotics and Automation, 13(3), 398–410.
- Siciliano, B. (1990). Kinematic control of redundant robot manipulators: A tutorial. Journal of Intelligent and Robotic Systems, 3(3), 201–212.
- Murray, R. M., Li, Z., & Sastry, S. S. (1994). A Mathematical Introduction to Robotic Manipulation. CRC Press, chapters on kinematics and task-space control.
- Spong, M. W., Hutchinson, S., & Vidyasagar, M. (2006). Robot Modeling and Control. Wiley, chapters on kinematic and operational-space control formulations.