A modular, production-quality framework for robotic manipulation — covering MuJoCo simulation, SO-ARM100 real hardware, motion planning, control, and analytics. Designed for sim-to-real transfer; all components are hardware-agnostic via injectable callables.
- MuJoCo simulation — URDF/MJCF loading, scene management, passive and interactive viewers
- 8 high-level controllers — Impedance, admittance, force, gravity compensation, trajectory following, pick-place, visual servoing, diff-IK, OSC
- Motion planners — joint-space cubic spline, RRT-Connect (pure NumPy), TOPP-RA time-optimal reparametrisation, minimum-jerk polynomials
- Task planner — ground-atom STRIPS BFS for multi-step manipulation sequences
- Behavior tree execution — 26 atomic BT nodes across motion / gripper / perception / safety / control domains
- SO-ARM100 hardware — full Feetech STS3215 servo SDK, non-blocking double-buffer writes, homing dashboard
- Analytics —
TelemetryBufferring buffer, Rerun live logging, offline matplotlib / plotly plots for trajectories, controller signals, and planning data - Streamlit dashboard — 7-tab interactive dashboard for control, planning, telemetry replay, config editing, and diagnostics
- Protocol-based design — all components are
typing.Protocol-typed, no inheritance required - 32 passing unit tests (pure NumPy, no MuJoCo required for most)
# Core package (simulation + control + planning + hardware)
pip install -e .
# stservo-sdk (SO-ARM100 hardware)
pip install -e stservo-sdk/
# Analytics extras (Rerun, matplotlib, plotly, Streamlit)
pip install -e ".[analysis]"Requirements: Python ≥ 3.10, MuJoCo ≥ 3.0, mink (differential IK).
# Pick-and-place demo (MuJoCo viewer)
mjpython examples/control/pick_place.py
# Keyboard teleoperation
mjpython examples/control/teleop_keyboard.py
# Modular planning pipeline
mjpython examples/planning/pick_place_modular.py# Record a trajectory and generate offline plots
python examples/analysis/trajectory_analysis.py
# Controller signal analysis
python examples/analysis/controller_analysis.pypython -m streamlit run scripts/dashboard.pypython -m streamlit run stservo-sdk/examples/homing_dashboard.py| Category | Script | Description |
|---|---|---|
| Control | examples/control/pick_place.py |
Full pick-and-place with controllers |
| Control | examples/control/teleop_keyboard.py |
Keyboard teleoperation |
| Planning | examples/planning/pick_place_modular.py |
Modular planning + execution |
| Simulation | examples/simulation/sim_basic.py |
Bare MuJoCo scene setup |
| Visualization | examples/visualization/collision_avoidance.py |
Collision avoidance demo |
| Visualization | examples/visualization/viewer_backends.py |
MuJoCo / Viser viewer comparison |
| Analysis | examples/analysis/trajectory_analysis.py |
Trajectory telemetry + plots |
| Analysis | examples/analysis/controller_analysis.py |
Controller signal analysis |
fullstack-manip/
├── fullstack_manip/ # Main Python package
│ ├── core/ # ManipulationPlant, Robot, Gripper, IK, Collision, interfaces
│ ├── control/ # 8 high-level controllers + PID + motion executor
│ ├── planning/ # MotionPlanner, RRTPlanner, TOPP-RA, min-jerk, task planner
│ ├── execution/ # Behavior trees (26 nodes), blackboard, skills
│ ├── simulation/ # MuJoCo loader, scene, viewers
│ ├── state_estimation/ # Camera calibration (stub)
│ ├── analysis/ # Telemetry, RerunLogger, offline plot functions
│ └── utils/ # Rate config, loop limiters
├── stservo-sdk/ # STS3215 servo SDK + homing dashboard
├── configs/ # YAML/JSON plant configs
├── examples/ # Usage examples (control, planning, simulation, analysis)
├── scripts/ # dashboard.py, demo scripts
├── tests/ # Unit tests (32 passing)
└── docs/ # Architecture, algorithms, roadmap, hardware docs
The fullstack_manip/analysis/ package provides opt-in telemetry instrumentation.
Attach a logger to any instrumented component; omit it and nothing is recorded.
from fullstack_manip.analysis import TelemetryBuffer, RerunLogger
# In-memory ring buffer
buf = TelemetryBuffer(maxlen=5000)
# Or stream to Rerun
logger = RerunLogger(application_id="arm_run")
# Pass to any instrumented component
from fullstack_manip.planning.sampling.rrt_planner import RRTPlanner
planner = RRTPlanner(..., telemetry_logger=buf)
result = planner.plan(...)
# Export and plot
import numpy as np
data = buf.to_numpy("joint_pos") # → ndarray (N, 6)
buf.save("run_001.npz")
from fullstack_manip.analysis.plot_trajectory import plot_joint_positions
fig = plot_joint_positions(data)
fig.savefig("joints.png")| File | Contents |
|---|---|
| docs/architecture.md | Package structure, protocols, data flow |
| docs/algorithms.md | Math reference for all algorithms |
| docs/implementation.md | Deep-dives: BT, Gripper, Visualization, Config, Analytics |
| docs/roadmap.md | What's done and what's next |
| docs/hardware-and-servo.md | SO-ARM100 / STS3215 servo reference |
MIT License — see LICENSE.