Week 10 — Grasping and Manipulation Day 7 of 7
The Week in One Paragraph
This week was about the hardest part of robotics to get right: making a robot hold something and do something useful with it. We started with the physics of a single contact point — normal force, tangential friction, and the friction cone that bounds what a contact can resist before it slips. From there we built up to the two conditions that make a grasp stable: force closure (the contacts can resist any external wrench by squeezing) and form closure (the geometry alone prevents motion, no squeezing needed). Day 3 turned those conditions into algorithms — you sample candidate grasps, score them against a quality metric like the Ferrari–Canny epsilon, and pick one that clears the bar. Day 4 moved from a static hold to moving the object inside the hand, which needs multi-fingered hands with enough degrees of freedom and a controller that keeps the contacts from breaking. Day 5 was engineering judgment: parallel-jaw grippers are cheap and reliable for pick-and-place, but a suction cup beats them on flat cardboard boxes, and a three-finger adaptive hand beats both when parts vary. Day 6 tied it together in PyBullet, where you build a scene, drop a gripper onto a mesh, close the fingers, and read back contact normals and forces to check whether your grasp actually has force closure. The through-line: a grasp is not a pose, it is a set of contacts with constraints, and everything — planning, control, hardware choice — follows from those constraints.
What Each Day Built
| Day | Topic | The one idea you must retain |
|---|---|---|
| 1 | Grasping Fundamentals | A contact can only push (normal force ≥ 0) and can only resist sideways force up to μ·f_n, so every contact is a cone in force space, not a point. |
| 2 | Force Closure and Form Closure | Force closure means the set of contact wrenches spans all 6 directions of wrench space (positive span); form closure means the contacts block all infinitesimal motions geometrically, with no friction required. |
| 3 | Grasp Planning | You cannot search the full 6-DOF grasp space, so you sample candidate poses on the object surface, filter by reachability and collision, then rank by a closure metric such as the Ferrari–Canny epsilon. |
| 4 | Dexterous Manipulation | In-hand manipulation requires either rolling/sliding contacts or finger gaiting; the hand needs at least 3 fingers for a planar reorient and the controller must keep every contact inside its friction cone throughout the motion. |
| 5 | Gripper Design and Selection | Match the end-effector to the part geometry and cycle time: parallel jaw for prismatic parts, suction for flat non-porous surfaces, soft/adaptive for fragile or irregular objects. |
| 6 | Python Practice: Grasp Simulation | PyBullet gives you contact normals and applied forces per link; project each contact force onto its friction cone and check the positive span to confirm closure in simulation before touching hardware. |
| 7 | Summary | The whole chain — contact model → closure test → planner → hand → simulation — is one pipeline, and a weak link anywhere (bad friction estimate, unreachable pose) breaks the grasp. |
Formula Cheat Sheet
| Formula | Symbols | Where it is used |
|---|---|---|
| |f_t| ≤ μ · f_n | f_t = tangential force at contact, f_n = normal force, μ = coefficient of friction | Contact model on Day 1; bounds every contact force and defines the friction cone half-angle α = arctan(μ). |
| α = arctan(μ) | α = friction cone half-angle, μ = friction coefficient | Day 1–2; a μ = 0.5 rubber-on-cardboard contact gives α ≈ 26.6°, which sets how far off-normal you can push before slip. |
| G · f = −w_ext, with f_i ∈ friction cone | G = grasp matrix (6×n, maps contact forces to object wrench), f = stacked contact force vector, w_ext = external wrench | Day 2; the core force-closure equation. A grasp is force-closed if positive combinations of contact wrenches span ℝ⁶. |
| ε = min over unit wrenches of max contact force ratio | ε = Ferrari–Canny epsilon quality, unit wrench = any 6D force/torque direction normalized | Day 3; the planner’s scoring function. Higher ε means the grasp resists a worst-case unit wrench with less internal squeezing. |
| rank(G) = 6 and all f_i interior to cones | G = grasp matrix, f_i = contact forces | Day 2–3; the practical test — full wrench-space rank plus strictly positive contact forces means robust closure with margin. |
| J^T · f = τ | J = hand Jacobian, f = contact forces, τ = joint torques | Day 4; converts desired fingertip forces into joint torques for the dexterous hand controller. |
| x_dot = J · q_dot | x_dot = fingertip velocity, J = Jacobian, q_dot = joint velocities | Day 4; keeps fingertips tracking the object during in-hand manipulation. |
Method Selection Guide
- Object is a rigid box, bin-picking at high rate, budget matters → parallel-jaw gripper with a two-contact antipodal grasp. Two contacts on opposing faces give force closure with the least hardware; check that the face width exceeds the jaw opening.
- Object is flat, non-porous, and light (cardboard, sheet metal, glass) → vacuum suction cup. One suction contact acts like a form-closed patch; verify the seal area and the vacuum pressure give a safety factor of at least 2 against the part weight plus acceleration.
- Object is fragile, irregular, or varies batch to batch (produce, castings) → soft or underactuated multi-finger hand. The compliance absorbs shape variation, and you accept lower positional accuracy in exchange for not crushing the part.
- You need to reorient the object inside the hand (screw insertion, regrasping for assembly) → multi-fingered dexterous hand with finger gaiting. Plan the contact schedule so at least three contacts stay closed at all times.
- You just need to know whether a candidate grasp will hold before building it → simulate in PyBullet, read contact normals and forces, project onto the friction cone, and run the positive-span test. This catches most bad grasps in minutes.
- Grasp must survive an unknown disturbance direction → require force closure with a healthy ε (0.1 or higher) rather than a marginal form-closed grasp; form closure with zero friction margin fails the moment the surface is oily.
Common Pitfalls (Learned the Hard Way)
| Pitfall | Why it happens | Fix |
|---|---|---|
| Assuming friction is higher than it is | Lab benches are clean; real parts have oil, dust, or release agent, dropping μ from 0.6 to 0.2 | Measure μ for your actual part and pad material with a pull test, and design for the worst case, not the catalog value. |
| Treating a point contact as able to pull | The contact model allows only pushing (f_n ≥ 0); a grasp that relies on tension is not physical | Check every contact force is positive after solving; if the solver returns negative normal force, the grasp is invalid. |
| Confusing form closure with force closure | Form closure needs no friction but is very hard to achieve with a two-finger gripper | For two-finger parallel jaws, always test force closure (positive span), not form closure. |
| Grasp pose is reachable but collides with the object | Planners check the gripper frame, not the full finger swept volume | Run a full collision check on the closed finger geometry, not just the TCP pose. |
| Ignoring the grasp matrix rank | A grasp can look symmetric but have rank-deficient G, leaving one wrench direction unresisted | Compute rank(G) explicitly; if it is below 6, add a contact or change the contact locations. |
| Simulating with default PyBullet friction | Default μ and contact parameters do not match your hardware | Set lateralFriction and spinningFriction per link to measured values before trusting simulation results. |
Self-Assessment
-
What is the friction cone, and what does its half-angle depend on? It is the set of all contact forces a point contact can apply without slipping: a normal component plus a tangential component bounded by μ·f_n. The half-angle is α = arctan(μ), so higher friction widens the cone.
-
State the difference between force closure and form closure. Force closure means the contacts can resist any external wrench by applying forces inside their friction cones — it needs friction. Form closure means the contact geometry alone blocks all motions with no friction required.
-
Why does a grasp planner sample candidate poses instead of searching exhaustively? The grasp space is 6-DOF per contact and continuous, so exhaustive search is intractable. Sampling plus a closure-metric ranking (e.g., Ferrari–Canny ε) finds good grasps in practical time.
-
When would you pick a suction gripper over a parallel-jaw gripper? When the part has a flat, non-porous surface and is light, and cycle time is short. Suction gives a large contact patch and fast pick, but fails on porous or curved surfaces where the seal breaks.
-
What does the hand Jacobian do in dexterous manipulation? It maps joint velocities to fingertip velocities (x_dot = J·q_dot) and, transposed, maps desired fingertip forces to joint torques (τ = J^T·f). It is how the controller keeps contacts closed while moving the object.
Worked Example: Choosing a Grasp for a Real Part
Put the week together on one concrete case. You must pick a 1.2 kg aluminum bracket, 140 mm long, 60 mm wide, with two flat parallel faces 60 mm apart and a 12 mm through-hole in the middle. Cycle time target is 1.5 s per pick, and the part arrives in a bin at random orientation.
Step 1 — Contact model. The two flat faces are ideal for hard-finger point contact with friction. Aluminum against a polyurethane jaw pad gives μ ≈ 0.7 (dry), so the friction cone half-angle is α = arctan(0.7) ≈ 35°.
Step 2 — How many contacts? Two antipodal contacts on opposing flat faces. Force closure with two hard-finger contacts is achievable when the line joining the contacts passes through the friction cones at both points — which it does for parallel faces and opposed normals. Check rank(G): two 3-DOF contacts give a 6×6 grasp matrix, and for antipodal contact on a rigid body it has full rank.
Step 3 — Force sizing. The part weighs 1.2 kg × 9.81 = 11.8 N. With a 1.5 s cycle the peak vertical acceleration is roughly 3 m/s², so inertial load ≈ 3.6 N. Worst-case slip load ≈ 15.4 N total, split across two contacts. Required normal force per contact:
$$f_n \geq \frac{W_{slip}}{2\mu} = \frac{15.4}{2 \times 0.7} = 11.0\ \text{N}$$
Apply a safety factor of 3 for surface contamination and acceleration spikes → 33 N per finger. Any 2F-85-class gripper at mid-stroke delivers 100 N+, so force is not the constraint.
Step 4 — Jaw stroke. Faces are 60 mm apart; the jaw must open past 60 mm plus bin clearance, so 85 mm stroke works with 12 mm margin per side.
Step 5 — For the hole. If you instead tried a 3-finger adaptive grasp into the 12 mm hole, the fingertips (typically 8 mm wide) would barely fit and the contact geometry would be poor. Skip it — the two flat faces are the better grasp.
Step 6 — Verify in simulation. Run the Day 6 PyBullet script with the bracket’s friction set to 0.7 and confirm the positive-span test returns true with ε > 0.1. If ε comes back near zero, the contacts are collinear with the centre of mass and the grasp is weak against rotation about that axis.
This is the whole pipeline from Day 1 to Day 6 applied in about fifteen minutes of engineering work — and it is the level of reasoning the rest of this site expects you to bring to a gripper problem.
Diagnostic Table: Symptom to Root Cause
When a grasp fails on the shop floor, the symptom usually points straight at one of this week’s concepts. Use this table before you start changing hardware.
| Symptom | Most likely root cause | Concept from | First thing to check |
|---|---|---|---|
| Part slips during acceleration but holds at rest | Insufficient normal force for the inertial load; friction cone violated under dynamic wrench | Day 1 | Recompute $f_n \geq W_{slip}/(n\mu)$ with real acceleration, then compare to actual grip force setting |
| Part rotates about one axis while jaws stay closed | Grasp matrix rank-deficient; contacts cannot resist that torque direction | Day 2 | Compute rank(G); if below 6, move contacts off the line through the centre of mass |
| Grasp works in simulation, fails on hardware | Simulation friction set to the default instead of measured μ | Day 6 | Measure μ with a pull test; set lateralFriction per link to the measured value |
| Same gripper works on one part, fails on another from the same batch | Surface finish variation (oil, release agent) changing μ | Day 1, Day 5 | Pull-test several parts from the batch, not just the first good one |
| Fingers crush the part before force closure is reached | Force-controlled closing without a compliance or force limit | Day 4, Day 5 | Add current or torque monitoring to the gripper; cap the closing force at the computed $f_n$ plus margin |
| Planner returns no feasible grasp | Candidate poses rejected by reachability or full-finger collision check | Day 3 | Check the closed-finger swept volume, not just the TCP frame |
Preview: Week 11
Next week we move from hand-coded grasp geometry to learned behavior: Machine Learning for Robotics. We will cover imitation learning from demonstrations, reinforcement learning for grasping policies, and how to train and evaluate a policy safely in simulation before deploying it on hardware. Bring your PyBullet scenes from this week — they become the training environment.