Chapter 8: Grasp Synthesis and Dexterous Manipulation Planning

Lesson 2: Antipodal and Multi-Finger Grasp Synthesis

This lesson develops analytical conditions and algorithmic pipelines for synthesizing antipodal grasps (two-point grasps) and multi-finger grasps on rigid objects. Building on the contact models, friction cones, and grasp wrench space introduced in Chapter 7, we derive geometric and convex-analytic criteria for force-closure, and translate them into implementable algorithms with examples in Python, C++, Java, MATLAB/Simulink, and Wolfram Mathematica.

1. Conceptual Overview

Consider a rigid object \( \mathcal{O} \subset \mathbb{R}^3 \) and a set of point contacts on its surface. From Chapter 7, each contact produces a wrench (force and moment) on the object, and the set of all wrenches obtainable under Coulomb friction defines the grasp wrench space. In this lesson we focus on two important subclasses:

  • Antipodal grasps: two contacts whose friction cones can generate equal and opposite forces, yielding strong resistance to disturbances along the line connecting the contacts.
  • Multi-finger grasps: three or more contacts whose combined wrenches achieve \( \text{force-closure} \), i.e., can balance any external wrench in the workspace of interest.

Let \( \mathbf{p}_i \in \mathbb{R}^3 \) be the contact position in the world frame, and \( \mathbf{n}_i \) the outward surface normal at contact \( i \). With friction coefficient \( \mu \), the (3D) Coulomb friction cone at contact \( i \) is

\[ C(\mathbf{n}_i,\mu) = \left\{ \mathbf{f}_i \in \mathbb{R}^3 \;:\; \mathbf{f}_i = f_{n,i} \mathbf{n}_i + \mathbf{f}_{t,i},\; f_{n,i} \geq 0,\; \|\mathbf{f}_{t,i}\| \leq \mu f_{n,i} \right\}. \]

An antipodal pair is informally a pair of contacts where the two friction cones can generate forces that are exactly opposite. A multi-finger grasp is force-closure when its primitive wrenches positively span the ambient wrench space, a condition we will make precise via convex hulls and linear programs.

2. Friction Cones and Antipodal Condition (Planar Case)

We first analyze the planar case, where object motion is restricted to the plane, so each contact force is \( \mathbf{f}_i \in \mathbb{R}^2 \) and the wrench space is \( \mathbb{R}^3 \) (two force components and one torque about the out-of-plane axis).

Let \( \mathbf{n}_i \) (unit) be the outward surface normal, and \( \mathbf{t}_i \) the tangential direction obtained by rotating \( \mathbf{n}_i \) by \( \pi/2 \). The friction cone in 2D reduces to a friction wedge with half-angle \( \varphi_f = \arctan(\mu) \). A planar force \( \mathbf{f}_i \) lies in the cone iff the angle between \( -\mathbf{n}_i \) (inward normal) and \( \mathbf{f}_i \) is at most \( \varphi_f \).

Definition (Antipodal grasp, planar version). Two contacts at positions \( \mathbf{p}_1,\mathbf{p}_2 \) with normals \( \mathbf{n}_1,\mathbf{n}_2 \) and friction coefficient \( \mu \) form an antipodal grasp if there exist forces \( \mathbf{f}_1 \in C(\mathbf{n}_1,\mu) \) and \( \mathbf{f}_2 \in C(\mathbf{n}_2,\mu) \) such that

\[ \mathbf{f}_1 + \mathbf{f}_2 = \mathbf{0}. \]

Geometrically, this means the two cones intersect in a nonzero vector and its negative. Let \( \mathbf{d} = \dfrac{\mathbf{p}_2 - \mathbf{p}_1}{\|\mathbf{p}_2 - \mathbf{p}_1\|} \) be the unit vector from contact 1 to contact 2.

Theorem (Planar geometric condition). The pair \( (\mathbf{p}_1,\mathbf{n}_1),(\mathbf{p}_2,\mathbf{n}_2) \) is antipodal if and only if

\[ \angle(-\mathbf{n}_1,\mathbf{d}) \leq \varphi_f \quad\text{and}\quad \angle(\mathbf{n}_2,\mathbf{d}) \leq \varphi_f. \]

Sketch of proof. If the angular conditions hold, choose \( \mathbf{f}_1 = \alpha \mathbf{d} \) with \( \alpha > 0 \). The angle constraint implies \( \mathbf{f}_1 \in C(\mathbf{n}_1,\mu) \). Setting \( \mathbf{f}_2 = -\alpha \mathbf{d} \) satisfies \( \mathbf{f}_2 \in C(\mathbf{n}_2,\mu) \) by the second constraint and yields \( \mathbf{f}_1 + \mathbf{f}_2 = \mathbf{0} \). Conversely, if an antipodal pair exists, any common direction of the cones must lie inside each cone, implying the angular inequalities.

3. 3D Antipodal Grasps and Approximate Tests

In 3D, Coulomb cones are true cones in \( \mathbb{R}^3 \) and exact geometric tests are more involved. A useful sufficient condition uses the friction cone half-angle \( \varphi_f = \arctan(\mu) \) and the line-of-centers direction \( \mathbf{d} \) as before.

Definition (3D antipodal, sufficient condition). Two contacts \( (\mathbf{p}_1,\mathbf{n}_1) \) and \( (\mathbf{p}_2,\mathbf{n}_2) \) form an antipodal grasp if there exists a unit vector \( \mathbf{u} \) with

\[ \mathbf{u} \in C(\mathbf{n}_1,\mu) \cap \left(-C(\mathbf{n}_2,\mu)\right), \]

and no collision or penetration of the hand is required to realize the corresponding fingertip directions. In practice, we often check the simpler conditions

\[ \angle(-\mathbf{n}_1,\mathbf{d}) \leq \varphi_f,\quad \angle(\mathbf{n}_2,\mathbf{d}) \leq \varphi_f,\quad \angle(\mathbf{n}_1,\mathbf{n}_2) \approx \pi. \]

The last constraint enforces near-opposition of the normals, which improves numerical robustness. Exact antipodality can be formulated as a feasibility problem over the intersection of two friction cones, but the above approximations are widely used in practical grasp synthesis algorithms.

Using the standard formula \( \cos \theta = \dfrac{\mathbf{a}^\top \mathbf{b}}{\|\mathbf{a}\|\|\mathbf{b}\|} \), the above angular constraints can be implemented purely with dot products and norms.

4. Multi-Finger Grasps and the Grasp Map \( \mathbf{G} \)

For a grasp with \( m \) fingertips, index contacts by \( i = 1,\dots,m \). Let \( \mathbf{p}_i \) be the contact point in the object frame, and \( \mathbf{f}_i \in \mathbb{R}^3 \) the contact force, expressed in the world frame. The resulting wrench on the object is

\[ \mathbf{w}_i = \begin{bmatrix} \mathbf{f}_i \\[2pt] \mathbf{p}_i \times \mathbf{f}_i \end{bmatrix} \in \mathbb{R}^6. \]

Stacking all contact forces into \( \mathbf{f}_c = [\mathbf{f}_1^\top,\dots,\mathbf{f}_m^\top]^\top \in \mathbb{R}^{3m} \), there exists a grasp map \( \mathbf{G} \in \mathbb{R}^{6 \times 3m} \) such that

\[ \mathbf{w} = \mathbf{G} \,\mathbf{f}_c = \sum_{i=1}^m \begin{bmatrix} \mathbf{I}_{3\times 3} \\ [2pt] [\mathbf{p}_i]_{\times} \end{bmatrix} \mathbf{f}_i, \]

where \( [\mathbf{p}_i]_{\times} \) is the skew-symmetric matrix implementing the cross product \( \mathbf{p}_i \times \mathbf{f}_i \). Static equilibrium with an external wrench \( \mathbf{w}_{\mathrm{ext}} \) requires

\[ \mathbf{G}\mathbf{f}_c + \mathbf{w}_{\mathrm{ext}} = \mathbf{0}. \]

In addition, each \( \mathbf{f}_i \) must lie in its friction cone \( C(\mathbf{n}_i,\mu) \) and must satisfy unilateral contact constraints (no tension). These constraints will be encoded into convex cones and approximated polyhedrally for algorithmic synthesis.

5. Force-Closure via Convex Hull of Primitive Wrenches

Following the standard approach in analytic grasping, we approximate each friction cone by a polyhedral cone generated by a finite set of unit contact forces \( \{\mathbf{g}_{i1},\dots,\mathbf{g}_{ik_i}\} \subset C(\mathbf{n}_i,\mu) \). Each generator \( \mathbf{g}_{ij} \) induces a primitive wrench

\[ \mathbf{w}_{ij} = \begin{bmatrix} \mathbf{g}_{ij} \\[2pt] \mathbf{p}_i \times \mathbf{g}_{ij} \end{bmatrix} \in \mathbb{R}^6. \]

Collect all primitive wrenches in the set \( \mathcal{W} = \{\mathbf{w}_{ij}\}_{i,j} \). Any feasible contact force vector consistent with the polyhedral approximation can be written as a nonnegative combination

\[ \mathbf{w} = \sum_{i,j} \lambda_{ij} \mathbf{w}_{ij},\quad \lambda_{ij} \geq 0. \]

Theorem (Standard force-closure criterion). A grasp has force-closure (for the approximated cones) if and only if

\[ \mathbf{0} \in \operatorname{int}\big( \operatorname{conv}(\mathcal{W}) \big), \]

where \( \operatorname{conv} \) denotes the convex hull.

Equivalently, force-closure holds if and only if there exist coefficients \( \lambda_{ij} \geq 0 \) such that

\[ \sum_{i,j} \lambda_{ij} \mathbf{w}_{ij} = \mathbf{0}, \quad \sum_{i,j} \lambda_{ij} = 1, \]

and at least \( 6 \) of the \( \lambda_{ij} \) are strictly positive (for 3D grasps) so that the convex combination spans all wrench directions. This provides a direct test in terms of a small linear program.

Proof sketch. By definition, a point lies in the convex hull of \( \mathcal{W} \) exactly when it can be written as a convex combination, i.e., a nonnegative combination with unit sum. Thus \( \mathbf{0} \in \operatorname{conv}(\mathcal{W}) \) is equivalent to the existence of \( \lambda_{ij} \) satisfying the above equations. Interior membership corresponds to positive spanning and robustness to perturbations.

6. Algorithmic Antipodal Grasp Synthesis

For a known object mesh with surface normals, one common approach to antipodal grasp synthesis is to sample pairs of surface points and check the geometric conditions from Sections 2–3. Below is a high-level pipeline for a parallel-jaw gripper.

flowchart TD
  A["Input: object mesh, friction mu"] --> B["Sample surface points and normals"]
  B --> C["Generate candidate point pairs consistent with gripper width"]
  C --> D["Compute line-of-centers direction d for each pair"]
  D --> E["Check angle constraints with normals and friction angle"]
  E --> F{"Antipodal?"}
  F -->|yes| G["Score grasp (wrench metric, clearance, etc.)"]
  F -->|no| C2["Discard pair"]
  C2 --> C
  G --> H["Select top-K antipodal grasps"]
        

The scoring step can reuse the grasp quality metrics from Chapter 7 (e.g., radius of the largest inscribed ball in the wrench hull). In practice, additional constraints such as collision-free approach directions and kinematic feasibility of the arm are imposed, but we defer those to later chapters on task and motion planning.

7. Multi-Finger Grasp Synthesis Pipelines

Multi-finger synthesis extends antipodal ideas to three or more fingertips. The typical analytic pipeline includes:

  1. Sampling or enumerating candidate fingertip sets on the object surface.
  2. Approximating friction cones and constructing primitive wrenches.
  3. Building the grasp map \( \mathbf{G} \) and testing the force-closure condition via convex hull or linear-program feasibility.
  4. Optionally optimizing the grasp according to a wrench-space quality metric.
flowchart TD
  S["Sample m fingertip candidates on object"] --> W["Compute normals and contact frames"]
  W --> P["Approximate friction cones with k generators per contact"]
  P --> G["Assemble primitive wrenches and grasp map G"]
  G --> FC["Solve LP: find positive lambda with sum=1 and W lambda = 0"]
  FC -->|feasible| Q["Evaluate quality metric (e.g. min wrench radius)"]
  FC -->|infeasible| R["Reject candidate grasp"]
  Q --> SEL["Keep top-scoring multi-finger grasps"]
        

Concretely, if we stack primitive wrenches into \( \mathbf{W} = [\mathbf{w}_1,\dots,\mathbf{w}_N] \in \mathbb{R}^{6 \times N} \), a standard force-closure LP is

\[ \text{find } \boldsymbol{\lambda} \in \mathbb{R}^N \text{ such that } \mathbf{W}\boldsymbol{\lambda} = \mathbf{0},\; \mathbf{1}^\top \boldsymbol{\lambda} = 1,\; \boldsymbol{\lambda} \geq \mathbf{0}. \]

Feasibility of this LP is exactly the convex-hull condition in Section 5. Numerical implementations usually use standard linear-program solvers (e.g. HiGHS in Python, quadprog in C++, Optimization Toolbox in MATLAB).

8. Python Lab — Antipodal Test and Grasp Map Construction

We now implement a basic antipodal test and a grasp map constructor in Python using numpy. In a full robotics stack this code would be combined with a simulation or perception library such as pybullet, trimesh, or open3d to obtain contact points and normals.


import numpy as np

def unit(v):
    """Return v normalized to unit length."""
    v = np.asarray(v, dtype=float)
    n = np.linalg.norm(v)
    if n == 0.0:
        raise ValueError("Zero vector cannot be normalized.")
    return v / n


def angle_between(a, b):
    """Return the angle between nonzero vectors a and b in radians."""
    a_u = unit(a)
    b_u = unit(b)
    cos_th = np.clip(np.dot(a_u, b_u), -1.0, 1.0)
    return np.arccos(cos_th)


def is_antipodal(p1, n1, p2, n2, mu, tol=1e-3):
    """
    Test the sufficient antipodal condition from Sections 2-3.

    Parameters
    ----------
    p1, p2 : array_like, shape (3,)
        Contact positions in world frame.
    n1, n2 : array_like, shape (3,)
        Outward surface normals at contacts.
    mu : float
        Coulomb friction coefficient.
    tol : float
        Numerical tolerance for angular inequalities.

    Returns
    -------
    bool
        True if the antipodal condition is satisfied.
    """
    p1 = np.asarray(p1, dtype=float)
    p2 = np.asarray(p2, dtype=float)
    n1 = unit(n1)
    n2 = unit(n2)

    d = unit(p2 - p1)
    phi = np.arctan(mu)

    theta1 = angle_between(-n1, d)
    theta2 = angle_between(n2, -d)
    theta_n = angle_between(n1, -n2)

    return (
        theta1 <= phi + tol
        and theta2 <= phi + tol
        and theta_n >= np.pi - 0.3  # normals roughly opposite
    )


def grasp_map(points, normals):
    """
    Construct a 6 x (3m) grasp map for point contacts with friction.

    For each contact i we build a 6x3 block [I; [p_i]_x] mapping contact-frame
    forces (expressed in world coordinates) into object wrenches.

    Parameters
    ----------
    points : array_like, shape (m, 3)
        Contact positions in object/world frame.
    normals : array_like, shape (m, 3)
        Outward surface normals (not used directly here but typically needed
        for friction-cone discretization).

    Returns
    -------
    G : ndarray, shape (6, 3m)
        Grasp map matrix.
    """
    pts = np.asarray(points, dtype=float)
    m = pts.shape[0]
    G = np.zeros((6, 3 * m))

    def skew(p):
        px, py, pz = p
        return np.array([[0.0, -pz,  py],
                         [pz,  0.0, -px],
                         [-py, px,  0.0]])

    for i, p in enumerate(pts):
        I = np.eye(3)
        px = skew(p)
        block = np.vstack((I, px))  # 6 x 3
        col_start = 3 * i
        col_end = col_start + 3
        G[:, col_start:col_end] = block

    return G


if __name__ == "__main__":
    # Example: two candidate contacts on a box-like object
    p1 = [0.05, 0.0, 0.0]
    p2 = [-0.05, 0.0, 0.0]
    n1 = [-1.0, 0.0, 0.0]
    n2 = [1.0, 0.0, 0.0]
    mu = 0.5

    print("Antipodal:", is_antipodal(p1, n1, p2, n2, mu))

    points = np.array([p1, p2])
    normals = np.array([n1, n2])
    G = grasp_map(points, normals)
    print("Grasp map shape:", G.shape)
      

To test force-closure for multi-finger grasps, extend this code by discretizing each friction cone into a small set of unit forces, constructing primitive wrenches, and solving the LP from Section 7 using scipy.optimize.linprog with nonnegative variables and equality constraints.

9. C++ Lab — Antipodal Test with Eigen

In C++ it is natural to use Eigen for linear algebra and integrate the resulting routines into a ROS / MoveIt planning pipeline. The snippet below shows the core antipodal test; in a full system, contact points and normals would be obtained from a perception module or from a physics engine such as Bullet or ODE.


#include <Eigen/Dense>
#include <cmath>
#include <stdexcept>

using Vec3 = Eigen::Vector3d;

inline Vec3 unit(const Vec3& v) {
    double n = v.norm();
    if (n == 0.0) {
        throw std::runtime_error("Zero vector cannot be normalized.");
    }
    return v / n;
}

double angle_between(const Vec3& a, const Vec3& b) {
    Vec3 au = unit(a);
    Vec3 bu = unit(b);
    double cos_th = au.dot(bu);
    if (cos_th > 1.0) cos_th = 1.0;
    if (cos_th < -1.0) cos_th = -1.0;
    return std::acos(cos_th);
}

bool isAntipodal(
    const Vec3& p1,
    const Vec3& n1_out,
    const Vec3& p2,
    const Vec3& n2_out,
    double mu,
    double tol = 1e-3
) {
    Vec3 n1 = unit(n1_out);
    Vec3 n2 = unit(n2_out);

    Vec3 d = unit(p2 - p1);
    double phi = std::atan(mu);

    double theta1 = angle_between(-n1, d);
    double theta2 = angle_between(n2, -d);
    double theta_n = angle_between(n1, -n2);

    return (theta1 <= phi + tol)
        && (theta2 <= phi + tol)
        && (theta_n >= M_PI - 0.3);
}

// Example integration in a ROS/MoveIt node:
// - Subscribe to a point cloud or mesh.
// - Compute candidate contacts and normals.
// - Call isAntipodal(p1, n1, p2, n2, mu) to filter pairs.
// - Pass surviving grasps to MoveIt as grasp candidates.
      

For multi-finger grasps, construct the grasp map \( \mathbf{G} \) as in Section 8, using Eigen matrices for \( [\mathbf{p}]_{\times} \), and then call a quadratic or linear programming library (e.g., OSQP, qpOASES) to perform the force-closure test.

10. Java Lab — Antipodal Test Skeleton

Java is less common in low-level robot control, but Java-based stacks (e.g., rosjava) are used in some systems. Below we implement a minimal 3D vector class and an antipodal test method suitable for integration with a Java perception pipeline.


public final class Vector3 {
    public final double x, y, z;

    public Vector3(double x, double y, double z) {
        this.x = x; this.y = y; this.z = z;
    }

    public Vector3 add(Vector3 o) {
        return new Vector3(x + o.x, y + o.y, z + o.z);
    }

    public Vector3 sub(Vector3 o) {
        return new Vector3(x - o.x, y - o.y, z - o.z);
    }

    public Vector3 mul(double s) {
        return new Vector3(s * x, s * y, s * z);
    }

    public double dot(Vector3 o) {
        return x * o.x + y * o.y + z * o.z;
    }

    public double norm() {
        return Math.sqrt(this.dot(this));
    }

    public Vector3 unit() {
        double n = norm();
        if (n == 0.0) {
            throw new IllegalArgumentException("Zero vector cannot be normalized.");
        }
        return this.mul(1.0 / n);
    }

    public static double angleBetween(Vector3 a, Vector3 b) {
        Vector3 au = a.unit();
        Vector3 bu = b.unit();
        double cos = au.dot(bu);
        if (cos > 1.0) cos = 1.0;
        if (cos < -1.0) cos = -1.0;
        return Math.acos(cos);
    }
}

public final class GraspGeometry {

    public static boolean isAntipodal(
            Vector3 p1,
            Vector3 n1Out,
            Vector3 p2,
            Vector3 n2Out,
            double mu,
            double tol) {

        Vector3 n1 = n1Out.unit();
        Vector3 n2 = n2Out.unit();

        Vector3 d = p2.sub(p1).unit();
        double phi = Math.atan(mu);

        double theta1 = Vector3.angleBetween(n1.mul(-1.0), d);
        double theta2 = Vector3.angleBetween(n2, d.mul(-1.0));
        double thetaN = Vector3.angleBetween(n1, n2.mul(-1.0));

        return (theta1 <= phi + tol)
                && (theta2 <= phi + tol)
                && (thetaN >= Math.PI - 0.3);
    }

    // Typical usage in rosjava:
    // - Convert PointCloud2 contacts to Vector3.
    // - Use isAntipodal(...) to filter candidate grasps before IK.
}
      

For more advanced numerical routines in Java, one can integrate linear algebra packages such as EJML or Apache Commons Math to implement the convex-hull and LP-based force-closure tests.

11. MATLAB/Simulink and Wolfram Mathematica Implementations

11.1 MATLAB function for antipodal grasp test


function flag = isAntipodalGrasp(p1, n1, p2, n2, mu, tol)
%ISANTIPODALGRASP Sufficient antipodal condition in 3D.
%   p1, p2 : 3x1 positions
%   n1, n2 : 3x1 outward normals
%   mu     : friction coefficient
%   tol    : angular tolerance (radians)

if nargin < 6
    tol = 1e-3;
end

p1 = p1(:); p2 = p2(:);
n1 = n1(:); n2 = n2(:);

n1 = n1 / norm(n1);
n2 = n2 / norm(n2);

d = (p2 - p1);
d = d / norm(d);

phi = atan(mu);

theta1 = angleBetween(-n1, d);
theta2 = angleBetween(n2, -d);
thetaN = angleBetween(n1, -n2);

flag = (theta1 <= phi + tol) && ...
       (theta2 <= phi + tol) && ...
       (thetaN >= pi - 0.3);
end

function th = angleBetween(a, b)
au = a / norm(a);
bu = b / norm(b);
c = max(-1.0, min(1.0, au' * bu));
th = acos(c);
end
      

In Simulink, this M-file can be wrapped in an Embedded MATLAB Function block inside a larger model that simulates the manipulator and object dynamics. A grasp planner block would output contact points and normals, feed them to isAntipodalGrasp, and enable or disable a closing controller depending on the test result.

11.2 Wolfram Mathematica prototype

Mathematica is convenient for prototyping analytic tests and visualizing friction cones and wrench spaces symbolically.


Unit[v_List] := Module[{n = Norm[v]},
  If[n == 0.0, Throw["Zero vector"], v/n]
];

AngleBetweenVec[a_List, b_List] := Module[{au, bu, c},
  au = Unit[a];
  bu = Unit[b];
  c = au.bu;
  c = Max[Min[c, 1.0], -1.0];
  ArcCos[c]
];

IsAntipodalGrasp[p1_List, n1Out_List, p2_List, n2Out_List, mu_, tol_: 1.*^-3] :=
 Module[{n1, n2, d, phi, th1, th2, thN},
  n1 = Unit[n1Out];
  n2 = Unit[n2Out];
  d = Unit[p2 - p1];
  phi = ArcTan[mu];
  th1 = AngleBetweenVec[-n1, d];
  th2 = AngleBetweenVec[n2, -d];
  thN = AngleBetweenVec[n1, -n2];
  (th1 <= phi + tol) && (th2 <= phi + tol) && (thN >= Pi - 0.3)
];

(* Example usage *)
p1 = {0.05, 0., 0.};
p2 = {-0.05, 0., 0.};
n1 = {-1., 0., 0.};
n2 = {1., 0., 0.};
mu = 0.5;

IsAntipodalGrasp[p1, n1, p2, n2, mu]
      

Mathematica can also be used to symbolically derive conditions such as the minimum friction coefficient required for antipodality under specific geometric constraints, further illuminating the theory behind the numerical tests.

12. Problems and Solutions

Problem 1 (Planar antipodal condition). Let a planar object have two contact points \( \mathbf{p}_1,\mathbf{p}_2 \in \mathbb{R}^2 \) with normals \( \mathbf{n}_1,\mathbf{n}_2 \) and friction coefficient \( \mu \). Show that the pair is antipodal if and only if there exists a scalar \( \alpha > 0 \) such that \( \alpha \mathbf{d} \in C(\mathbf{n}_1,\mu) \) and \( -\alpha \mathbf{d} \in C(\mathbf{n}_2,\mu) \), where \( \mathbf{d} \) is the line-of-centers direction.

Solution. By the definition of an antipodal pair, there exist forces \( \mathbf{f}_1 \in C(\mathbf{n}_1,\mu) \) and \( \mathbf{f}_2 \in C(\mathbf{n}_2,\mu) \) with \( \mathbf{f}_1 + \mathbf{f}_2 = \mathbf{0} \). In the planar case the only internal force that can be balanced by two contacts without net moment along the line of centers is a pair of equal and opposite forces aligned with \( \mathbf{d} \), so \( \mathbf{f}_1 = \alpha \mathbf{d} \) and \( \mathbf{f}_2 = -\alpha \mathbf{d} \) for some \( \alpha > 0 \). Conversely, if such an \( \alpha \) exists, taking \( \mathbf{f}_1 = \alpha \mathbf{d} \) and \( \mathbf{f}_2 = -\alpha \mathbf{d} \) clearly yields a valid antipodal pair. Thus the statement holds.

Problem 2 (Friction angle bound). For the planar contact of Problem 1, derive an explicit bound on the angle between \( -\mathbf{n}_1 \) and \( \mathbf{d} \) in terms of \( \mu \) such that \( \alpha \mathbf{d} \in C(\mathbf{n}_1,\mu) \).

Solution. Write \( \mathbf{f} = \alpha \mathbf{d} \). By the friction-cone definition, \( \mathbf{f} \in C(\mathbf{n}_1,\mu) \) iff \( f_n \geq 0 \) and \( |f_t| \leq \mu f_n \), where \( f_n \) and \( f_t \) are the normal and tangential components of \( \mathbf{f} \) with respect to the contact frame. In planar geometry these conditions are equivalent to constraining the angle \( \theta = \angle(-\mathbf{n}_1,\mathbf{f}) \) to lie in the interval \( [-\varphi_f,\varphi_f] \), where \( \varphi_f = \arctan(\mu) \). Thus \( \alpha \mathbf{d} \in C(\mathbf{n}_1,\mu) \) is equivalent to

\[ \angle(-\mathbf{n}_1,\mathbf{d}) \leq \varphi_f = \arctan(\mu). \]

Problem 3 (Convex-hull characterization of force-closure). Let \( \mathcal{W} = \{\mathbf{w}_1,\dots,\mathbf{w}_N\} \subset \mathbb{R}^6 \) be primitive wrenches for a grasp. Show that \( \mathbf{0} \in \operatorname{conv}(\mathcal{W}) \) if and only if there exist \( \lambda_i \geq 0 \) with \( \sum_i \lambda_i = 1 \) and \( \sum_i \lambda_i \mathbf{w}_i = \mathbf{0} \).

Solution. By the definition of convex hull, \( \operatorname{conv}(\mathcal{W}) \) is the set of all convex combinations \( \sum_i \lambda_i \mathbf{w}_i \) where \( \lambda_i \geq 0 \) and \( \sum_i \lambda_i = 1 \). Therefore \( \mathbf{0} \in \operatorname{conv}(\mathcal{W}) \) is equivalent to the existence of coefficients with exactly those properties such that the combination equals \( \mathbf{0} \). This is precisely the pair of equations in the problem statement.

Problem 4 (Minimum number of contacts). Consider frictionless point contacts in the plane, so each contact wrench has only a normal force and the associated torque. Show that at least three frictionless contacts are required to achieve force-closure in planar motion.

Solution. With a single contact, only one force direction (normal to the surface) is available, so the set of achievable wrenches is a ray in the 3D planar wrench space. With two contacts, any wrench is still a nonnegative combination of two primitive wrenches, so all achievable wrenches lie in the convex cone spanned by these two vectors, which is at most two-dimensional. Since the planar wrench space is 3D (two forces and one torque), a two-dimensional cone cannot contain a neighborhood of the origin. Thus force-closure, which requires that an open ball around the origin be representable as internal wrenches, is impossible with fewer than three frictionless contacts. With three well-placed contacts (forming a nondegenerate triangle and appropriate torque directions) the primitive wrenches can positively span the whole 3D wrench space, yielding force-closure.

Problem 5 (Effect of friction coefficient on antipodal feasibility). In the planar case, suppose the angle between \( -\mathbf{n}_1 \) and \( \mathbf{d} \) is \( \theta \). What is the minimum friction coefficient \( \mu_{\min} \) such that contact 1 can participate in an antipodal pair along \( \mathbf{d} \)?

Solution. From Problem 2, we require \( \theta \leq \varphi_f = \arctan(\mu) \), hence \( \mu \geq \tan(\theta) \). Therefore the minimum friction coefficient that allows \( \mathbf{d} \) to stay inside the cone at contact 1 is

\[ \mu_{\min} = \tan(\theta). \]

In a symmetric setting where contact 2 has the same angular offset, this is also the minimum friction coefficient that allows the pair to be antipodal along \( \mathbf{d} \).

13. Summary

In this lesson we developed analytic tools for synthesizing antipodal and multi-finger grasps. We expressed Coulomb friction cones as convex sets, derived geometric conditions for antipodal pairs in 2D and 3D, and represented multi-finger contacts through the grasp map \( \mathbf{G} \). Using polyhedral approximations of friction cones, we characterized force-closure via membership of the origin in the convex hull of primitive wrenches, leading to linear-program feasibility tests. Finally, we implemented these ideas in several programming languages and discussed how to connect them to common robotics software stacks. These constructions will be reused in later lessons on re-grasping, in-hand manipulation, and tactile-aware grasp refinement.

14. References

  1. Nguyen, V.-D. (1988). Constructing force-closure grasps. International Journal of Robotics Research, 7(3), 3–16.
  2. Mishra, B., Schwartz, J. T., & Sharir, M. (1987). On the existence and synthesis of multifinger positive grips. Algorithmica, 2(4), 541–558.
  3. Markenscoff, X., Ni, L., & Papadimitriou, C. H. (1990). The geometry of grasping. International Journal of Robotics Research, 9(1), 61–74.
  4. Ferrari, C., & Canny, J. (1992). Planning optimal grasps. Proceedings of the IEEE International Conference on Robotics and Automation, 2290–2295.
  5. Murray, R. M., Li, Z., & Sastry, S. S. (1994). A Mathematical Introduction to Robotic Manipulation. CRC Press.
  6. Bicchi, A. (2000). Hands for dexterous manipulation and robust grasping: A difficult road toward simplicity. IEEE Transactions on Robotics and Automation, 16(6), 652–662.
  7. Pollard, N. S. (2004). Closure and quality equivalence for efficient synthesis of grasps from examples. IJRR, 23(6), 595–614.
  8. Prattichizzo, D., & Trinkle, J. C. (2016). Grasping. In Springer Handbook of Robotics (2nd ed., pp. 955–988).