Each picking arm is a real planar 2-link manipulator. Given a target fruit at offset (dx, dy) from the shoulder joint, the elbow angle is solved with the law of cosines and the shoulder angle follows from the standard 2-link inverse-kinematics identity:
r = sqrt(dx^2 + dy^2)
cosE = (r^2 - L1^2 - L2^2) / (2 L1 L2)
theta2 = acos(clamp(cosE, -1, 1)) // elbow bend
theta1 = atan2(dy,dx) - atan2(L2 sin(theta2), L1 + L2 cos(theta2))
A greedy scheduler assigns each free arm the nearest unpicked, reachable (r ≤ L1+L2) fruit in its rail window. Once the arm converges on the solved joint angles, a vision check fires: detection probability = vision accuracy − occlusion penalty, where occlusion is highest for fruit buried deep in the canopy interior and lowest for fruit at the canopy edge. A failed check leaves the fruit on the tree and the arm re-targets; a success removes the fruit and adds it to the crate. The rail carries every arm's base forward at the chosen speed, continuously exposing fresh canopy.
- Reach circle — dashed arc around each arm base = L1+L2, the arm's true workspace boundary.
- Fruit colour — green (untouched) fades red with occlusion; grey = already picked.
- Vision accuracy vs canopy density is the real trade-off: denser canopies raise average occlusion, which the accuracy slider must compensate for to hold the miss rate down.