# Hazel-box / PLA-tube sorting update — 2026-09-22

The canonical task remains `Mjlab-GS-TubeSort-UR5` in `~/mjlab_gs`.
Its asset contract is now `tube-sort-v2-free-hazel-pla`. Old ACT weights,
datasets and evaluation rates have not been validated on this changed task.

## Assets and physics

Copied the supplied `hazel_500ml_box`, `red_pla_tube_20x16x80` and
`blue_pla_tube_20x16x80` packages into `assets/objects/real2sim/`.
The three boxes are independent **free** entities, each 16 g, using the supplied
rounded/tapered shell visual mesh and convex collision parts. The source
16 g inertia is preserved. Their outer size is 175 × 120 × 36 mm.
The free tubes use the supplied hollow visual mesh and all 32 convex shell
sectors, 20 mm OD / 16 mm ID × 80 mm, with the source 10 g hollow-shell inertia.
Visual and collision parts carry no additional mass. Per-world tube appearance
uses red/blue RGBA; the packaged PLA textures are retained but not applied.
Tube radius/length randomization is disabled because mesh vertices are shared
across GPU worlds. Unsupported geometry-scale overrides now fail explicitly.
Default tube mass randomization is also disabled; nominal mass is always 10 g.

All boxes use identical geometry, at x = −205, 0, +205 mm, y = −156 mm.
The conservative floor-level planning rectangle is 149 × 94 mm; actual
collisions use the rounded/tapered shell. Raised floor height is 4 mm.
Box reset poses follow table randomization, then evolve under physics.
Box jitter is reduced to ±5 mm / ±2 degrees to preserve the 30 mm gap
between the new shells at reset.
Contact time constant is 10 ms, with zero free-joint damping/armature; controller
gains and effort limits are unchanged. Contact capacities were raised to support
the detailed shell parts. Robot-box contacts remain part of physical validity.

## Expert and scoring

Reused the bin-picking `GripperCalibration` method on a read-only CPU replica
to extend the tube expert's gripper lookup below −0.7. The former minimum gap
was 20.2 mm, too wide for a 20 mm tube. Measured added gap samples are 0.520,
7.184, 13.808 and 17.096 mm at commands −1, −0.9, −0.8 and −0.75.
No gripper gains or friction were increased to force a grasp.

A preliminary recording showed the expert catching the rim and dragging a
box over a destination. The old index-based basket classification falsely
credited tubes still inside the dragged source box. Classification now resolves
overlapping basins by the closest floor, excludes tipped boxes (upright cosine
≤0.95), and requires tubes to be currently slow for a placement. Regression
tests cover dragged overlapping boxes and tipped/below-floor cases.
This is a conservative basin assignment, not a full support-contact proof.

The recorded v3 run uses the corrected scoring: 2/8 tubes sorted, 0/2
episodes fully sorted, and 0/2 task successes. Both episodes pass the configured
contact/speed gate despite large box movement; that gate is not a check that
the intended object alone was held. It retains the existing
side/end grasp search and nudge recovery; the expert can still touch or move
the small light boxes. Failed physical validity is reported separately from
sorted counts. Its horizon is 900 control steps (45 seconds) per episode.
Wrist videos are 20 fps; external videos are 4 fps, both at real simulation speed.
External images use a read-only pose replica with Gaussian room background;
no rendering operation steps live physics. The run saves qpos for future replay.

## Validation and reproduction

Run from `~/mjlab_gs` after `source env.sh`:

```bash
python -m pytest tests/test_tubesort.py tests/test_tubesort_pile.py tests/test_tubesort_expert.py tests/test_tubesort_free_boxes.py tests/test_binpick.py -q
python scripts/validate_tubesort.py --num-envs 2 --settle-steps 100 --output reports/new_tube_validation/validation.json
python scripts/audit_tubesort_free_boxes.py --output reports/new_tube_validation/free_boxes.json
python scripts/evaluate_tubesort.py unused --expert --episodes 2 --num-envs 2 --max-steps 900 --seed 22 --task-config configs/tubesort_nominal.json --videos 2 --external-video --device cuda:1 --output evaluations/new_hazel_expert
```

40 targeted tests passed. In the two-world nominal settling check, all 8 tubes
remained in the centre boxes; maximum final speed was 0.167 mm/s. The separate
force audit measured tube penetration up to 1.127 mm during settling and verified
exact body masses. Applying 0.2 N to an empty box for 0.1 s produced about 35 mm
translation; it was not fixed or pinned. These are small development checks,
not a broad robustness claim. `validation.json`'s penetration field is robot
contact penetration; `free_boxes.json` measures active-tube contact penetration.

`source_before/` preserves the prior tube implementation. `source_final/`
preserves the revised task and recording code. Incomplete preliminary v1/v2
recordings are diagnostic only and are not published as evaluated outcomes.

## Bin-picking review and next work

The current canonical bin-picking work is under `tasks/binpick`, not the older
standalone `~/binpick_sim` study. It includes mesh cross-section grasp candidates,
multiple yaw/tilt/height trials, sampled IK/collision checks, slip detection,
recovery, and support-verified placement. Its D415-specific assembly and mixed
object layout are separate from this tube-sort asset update. The existing
bin-picking tests pass; a new mixed-object performance benchmark was not run.

The next useful transfer is posed gripper/box collision screening before descent,
followed by held-object identity checks (reject a held box), live destination
tracking, and support-verified tube release. Tube geometry reduces the search
space, but the smaller movable bins add constraints absent from the old sorter.
The old ACT student needs new demonstrations and fresh evaluation before its
performance can be described on this scene.
