Project 8: scripted pick-and-place on the 7-DOF arm

Level 10 (after Lessons 10.1 and 10.2; Projects 5 or 6) · Time 4 to 6 hours · Difficulty 3 of 5

Objective

A state machine on models/pick_place.xml that puts all three cubes in the tray: approach, descend, close, lift, transport, place, release, retreat, once per cube. It must also tell the truth. For every cube it reports either “success”, checked from where the cube ended up, or the stage at which it failed, checked from the world (contacts, positions), never from the plan.

Prerequisites

Starter code

Expected behaviour

The reference converts each waypoint to joint angles with mjcourse.kinematics.solve_ik_restarts, follows minimum-jerk joint paths with PD and gravity compensation, and places the cubes at three slots 3 cm from the tray’s centre lines, nearest cube first. It checks the grasp from contacts and the jaw opening after closing, after lifting and after carrying.

Tests

MJC_IMPL=starter pytest projects/p08_pick_place
pytest projects/p08_pick_place

Three tests, run on 100 held-out layouts in parallel processes (about 7 s):

python tools/mutate_project.py p08_pick_place checks the mutants in mutants.json. One of them, ignoring the cube’s yaw, is a control that must pass (see below). The scene starts its worker processes with spawn, so a script of yours that calls run_many must keep its top-level code under if __name__ == "__main__":.

Common failures

Extension challenges

  1. Stack the three cubes in the tray, and add “fell off the stack” to the categories.
  2. Add 5 mm of Gaussian error to the cube positions you read, and keep the 90% rate with retries driven by the contact check.
  3. Halve the time per episode. Report which stage you shortened and what it cost, with Wilson intervals.

Solution

solution.py, about 110 lines.