craigm26 / craigm26/OpenCastor
The bigger robot: Pi 5 host with a pair of SO-ARM101s (bimanual)
- Dominant language
- Python
- Stars
- 28
- Forks
- 5
- PR merge metrics
- No merged PRs in 30d
Description
## The fleet, as the operator named it (2026-08-17)
- **Rover v2 (small)**: ESP32-C6 host + Maestro (ordered, Pololu #1350) + RC car + mounted iPhone running a LOCAL on-device model, always listening. No Pi anywhere. The phone is the brain; the board is the contract. (#941 carries the build.)
- **The bigger robot (this issue)**: a new platform hosting the Pi 5 and a PAIR of SO-ARM101 arms — bimanual manipulation on the full OpenCastor host (castor up, console, local Ollama brains, memory recall, gap rail).
## What the Pi 5 brings that the MCU class cannot
Local models (qwen chat, gemma vision, nomic memory), the console with recall-grounded chat, the gap rail, SmolVLA serving when #940 matures — the intelligence tier. The rover donates its Pi when v2 ships.
## Known constraints, written down before they bite
- **The multi-actuator rule (standing, from the host-config rail):** do NOT flip the gateway to multi-actuator dispatch before clients send `actuator_name` — it 422s every existing caller. Two arms means two actuators; the migration order is: app sends `actuator_name` first, gateway accepts-and-ignores, THEN the flip.
- Two arms on one servo-bus story needs deciding: two Feetech buses vs one bus with ID ranges; the safety bridge (castor/hardware/so_arm101/safety_bridge.py) currently assumes one arm's joint map.
- Bimanual is where SmolVLA (#940) stops being optional — teleop demo recording for two arms, phase 1 unchanged.
- Bob's wrist/OAK-D cameras are still physically unplugged; the bigger robot inherits that checklist.
## First milestones
1. Second SO-ARM101 acquired + both arms enumerated on the bench
2. `actuator_name` threading end to end (app -> gateway -> dispatch), single-arm behavior byte-identical until the flip
3. Dual-arm manifest: capabilities namespaced per arm (arm.left.* / arm.right.* or actuator-qualified), declared via the gap rail
4. One signed action moving each arm independently, receipts distinguishing them
Contributor guide
Research direction
Start with castor/hardware/so_arm101/safety_bridge.py and the host-config rail, then trace actuator_name through the app, gateway, and dispatch paths. The work is done when both arms are enumerated, single-arm behavior remains unchanged, capabilities are namespaced in the gap rail, and signed actions produce distinct receipts for each arm.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- ollama, python, raspberry-pi
- Domain
- ai, embedded-iot, robotics
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100