robotics-software-principles
Foundational software design principles applied specifically to robotics module development. Use this skill when designing robot software modules, structuring codebases, making architecture decisions, reviewing robotics code, or building reusable robotics libraries. Trigger whenever the user mentions SOLID principles for robots, modular robotics software, clean architecture for robots, dependency injection in robotics, interface design for hardware, real-time design constraints, error handling strategies for robots, configuration management, separation of concerns in perception-planning- control, composability of robot behaviors, or any discussion of software craftsmanship in a robotics context. Also trigger for code reviews of robotics code, refactoring robot software, or designing APIs for robotics libraries.
What this skill does
# Robotics Software Design Principles
## Why Robotics Software Is Different
Robotics code operates under constraints that most software never faces:
1. **Physical consequences** — A bug doesn't just crash a process, it crashes a robot into a wall
2. **Real-time deadlines** — Missing a 1ms control loop deadline can cause oscillation or damage
3. **Sensor uncertainty** — All inputs are noisy, delayed, and occasionally wrong
4. **Hardware diversity** — Same algorithm must work on 10 different grippers from 5 vendors
5. **Sim-to-real gap** — Code must run identically in simulation and on real hardware
6. **Long-running operation** — Robots run for hours/days; memory leaks and drift matter
7. **Safety criticality** — Some failures must NEVER happen, regardless of software state
These constraints demand disciplined design. Below are principles that account for them.
---
## Principle 1: Single Responsibility — One Module, One Job
Every module (node, class, function) should have exactly ONE reason to change.
**Why it matters in robotics**: A perception module that also does control means a camera driver update can break your arm controller. In safety-critical systems, this coupling is unacceptable.
```python
# ❌ BAD: God module — perception + planning + control + logging
class RobotController:
def __init__(self):
self.camera = RealSenseCamera()
self.detector = YOLODetector()
self.planner = RRTPlanner()
self.arm = UR5Driver()
self.logger = DataLogger()
def run(self):
image = self.camera.capture()
objects = self.detector.detect(image)
path = self.planner.plan(objects[0].pose)
self.arm.execute(path)
self.logger.log(image, objects, path)
# If ANY of these changes, you touch this class
# ✅ GOOD: Separated responsibilities with clear interfaces
class PerceptionModule:
"""ONLY responsibility: raw sensor data → detected objects"""
def __init__(self, camera: CameraInterface, detector: DetectorInterface):
self.camera = camera
self.detector = detector
def get_detections(self) -> List[Detection]:
image = self.camera.capture()
return self.detector.detect(image)
class PlanningModule:
"""ONLY responsibility: goal + world state → trajectory"""
def __init__(self, planner: PlannerInterface):
self.planner = planner
def plan_to(self, target: Pose, obstacles: List[Obstacle]) -> Trajectory:
return self.planner.plan(target, obstacles)
class ExecutionModule:
"""ONLY responsibility: trajectory → hardware commands"""
def __init__(self, arm: ArmInterface):
self.arm = arm
def execute(self, trajectory: Trajectory) -> ExecutionResult:
return self.arm.follow_trajectory(trajectory)
```
**Test**: Can you describe what a module does WITHOUT using "and"? If not, split it.
---
## Principle 2: Dependency Inversion — Depend on Abstractions, Not Hardware
High-level modules (planning, behavior) should never depend on low-level modules (drivers, hardware). Both should depend on abstractions.
**Why it matters in robotics**: This is the foundation of sim-to-real. If your planner imports `UR5Driver` directly, it can't run in simulation. If it depends on `ArmInterface`, you swap implementations freely.
```python
from abc import ABC, abstractmethod
from dataclasses import dataclass
from typing import List, Optional
import numpy as np
# ─── ABSTRACTIONS (the contracts) ────────────────────────────
class ArmInterface(ABC):
"""Abstract arm — every arm implementation must honor this contract"""
@abstractmethod
def get_joint_positions(self) -> np.ndarray:
"""Returns current joint positions in radians"""
...
@abstractmethod
def get_ee_pose(self) -> Pose:
"""Returns current end-effector pose"""
...
@abstractmethod
def move_to_joints(self, positions: np.ndarray,
velocity: float = 0.5) -> bool:
"""Move to joint positions. Returns True on success."""
...
@abstractmethod
def stop(self) -> None:
"""Immediately stop all motion"""
...
@property
@abstractmethod
def joint_limits(self) -> List[tuple]:
"""Returns [(min, max)] for each joint"""
...
class CameraInterface(ABC):
"""Abstract camera — any RGB camera must honor this"""
@abstractmethod
def capture(self) -> np.ndarray:
"""Returns (H, W, 3) uint8 RGB image"""
...
@abstractmethod
def get_intrinsics(self) -> CameraIntrinsics:
"""Returns camera intrinsic parameters"""
...
@property
@abstractmethod
def resolution(self) -> tuple:
"""Returns (width, height)"""
...
class GripperInterface(ABC):
@abstractmethod
def open(self, width: float = 1.0) -> bool: ...
@abstractmethod
def close(self, force: float = 0.5) -> bool: ...
@abstractmethod
def get_width(self) -> float: ...
@abstractmethod
def is_grasping(self) -> bool: ...
# ─── CONCRETE IMPLEMENTATIONS ────────────────────────────────
class UR5Arm(ArmInterface):
"""Real UR5 via RTDE protocol"""
def __init__(self, ip: str):
self.rtde = RTDEControl(ip)
self.rtde_receive = RTDEReceive(ip)
def get_joint_positions(self) -> np.ndarray:
return np.array(self.rtde_receive.getActualQ())
def move_to_joints(self, positions, velocity=0.5):
self.rtde.moveJ(positions.tolist(), velocity)
return True
def stop(self):
self.rtde.stopScript()
@property
def joint_limits(self):
return [(-2*np.pi, 2*np.pi)] * 6
class MuJoCoArm(ArmInterface):
"""Simulated arm in MuJoCo — SAME interface"""
def __init__(self, model_path: str, joint_names: List[str]):
self.model = mujoco.MjModel.from_xml_path(model_path)
self.data = mujoco.MjData(self.model)
self.joint_ids = [mujoco.mj_name2id(self.model, mujoco.mjtObj.mjOBJ_JOINT, n)
for n in joint_names]
def get_joint_positions(self) -> np.ndarray:
return np.array([self.data.qpos[jid] for jid in self.joint_ids])
def move_to_joints(self, positions, velocity=0.5):
# Simulate motion with position control
self.data.ctrl[:len(positions)] = positions
for _ in range(100):
mujoco.mj_step(self.model, self.data)
return True
def stop(self):
self.data.ctrl[:] = 0
# ─── HIGH-LEVEL CODE DEPENDS ONLY ON ABSTRACTIONS ────────────
class PickPlaceTask:
"""This class works with ANY arm + gripper + camera.
It never knows or cares if it's sim or real."""
def __init__(self, arm: ArmInterface, gripper: GripperInterface,
camera: CameraInterface, detector: DetectorInterface):
self.arm = arm
self.gripper = gripper
self.camera = camera
self.detector = detector
def execute(self, target_class: str) -> bool:
image = self.camera.capture()
detections = self.detector.detect(image)
target = next((d for d in detections if d.label == target_class), None)
if target is None:
return False
self.arm.move_to_joints(self.ik(target.pose))
self.gripper.close()
self.arm.move_to_joints(self.place_joints)
self.gripper.open()
return True
```
**The Dependency Rule in Robotics**:
```
Application / Tasks
↓ depends on
Interfaces (ABC)
↑ implements
Hardware Drivers / Simulators
```
Arrows point inward. High-level policy never imports low-level drivers.
---
## Principle 3: Open-Closed — Extend Without Modifying
Modules should be open for extension but closed for modification. Add new capabilities by adding new code, not changing existing code.
**Why it matters in robotics**: You constantly add new sensors, new robots, new tasks. If adding a new camera requires modifying your perception pipeRelated in Design
contribute
IncludedLocal-only OSS contribution command center. Auto-refreshes the user's in-flight PR and issue state on invoke so conversations start with full context — no need to brief Claude on what's in flight. Helps the user find issues to contribute to on GitHub, builds per-repo dossiers of what each upstream expects (CLA, DCO, branch convention, AI policy, draft-first, review bots, issue templates), runs deterministic gates before any external action so AI-assisted contributions don't reach maintainers as slop. State is markdown-only: candidate files at ~/.contribute-system/candidates/, repo dossiers at ~/.contribute-system/research/, append-only event log at ~/.contribute-system/log.jsonl. No database, no cloud calls. Use when the user asks about their PRs / issues / contributions, wants to find new work to take on, claim an issue, build/refresh a repo's dossier, or draft a Design Issue or PR. Trigger with "/contribute", "what's my PR status", "find a contribution", "claim issue X", "draft a Design Issue for Y", "refresh dossier for Z".
architectural-analysis
IncludedUser-triggered deep architectural analysis of a codebase or scoped subtree across eight modes — information architecture, data flow, integration points, UI surfaces, interaction patterns, data model, control flow, and failure modes. This skill should be used when the user asks to "diagram this codebase," "map the architecture," "show the data flow," "give me an ERD," "trace control flow," "find the integration points," "verify the layout pattern," "audit the UX architecture," or any similar request whose primary deliverable is mermaid diagrams plus cited reports under docs/architecture/. Dispatches haiku/sonnet sub-agents in parallel for per-mode exploration, then verifies every citation mechanically before any node lands in a diagram. Not for one-off prose explanations of code (use code-explanation) or for high-level system design from scratch (use system-design).
mcp
IncludedModel Context Protocol (MCP) server development and tool management. Languages: Python, TypeScript. Capabilities: build MCP servers, integrate external APIs, discover/execute MCP tools, manage multi-server configs, design agent-centric tools. Actions: create, build, integrate, discover, execute, configure MCP servers/tools. Keywords: MCP, Model Context Protocol, MCP server, MCP tool, stdio transport, SSE transport, tool discovery, resource provider, prompt template, external API integration, Gemini CLI MCP, Claude MCP, agent tools, tool execution, server config. Use when: building MCP servers, integrating external APIs as MCP tools, discovering available MCP tools, executing MCP capabilities, configuring multi-server setups, designing tools for AI agents.
react-native-skia
IncludedDesign, build, debug, and optimise high-polish animated graphics in React Native or Expo using @shopify/react-native-skia, Reanimated, and Gesture Handler. Use when the user wants canvas-driven UI, shaders, paths, rich text, image filters, sprite fields, Skottie, video frames, snapshots, web CanvasKit setup, or performance tuning for custom motion-heavy elements such as loaders, hero art, cards, charts, progress indicators, particle systems, or gesture-driven surfaces. Also use when the user asks for fluid, glow, glass, blob, parallax, 60fps/120fps, or GPU-friendly animated effects in React Native, even if they do not explicitly say "Skia". Do not use for ordinary form/layout work with standard views.
plaid
IncludedProduct Led AI Development — guides founders from idea to launched product. Six capabilities: Idea (discover a product idea), Validate (pressure-test the idea against fatal flaws, problem reality, competition, and 2-week MVP feasibility), Plan (vision intake + document generation), Design (translate image references into a design.md spec), Launch (go-to-market strategy), and Build (roadmap execution). Use when someone says "PLAID", "plaid idea", "help me find an idea", "product idea", "idea from my business", "idea from my expertise", "plaid validate", "validate my idea", "pressure-test", "is this idea good", "find fatal flaws", "validate the problem", "plan a product", "define my vision", "generate a PRD", "product strategy", "plaid design", "design from image", "translate image to design", "create design.md", "extract design tokens", "plaid launch", "go-to-market", "launch plan", "GTM strategy", "launch playbook", "plaid build", "build the app", "start building", or "execute the roadmap".
nextjs-framer-motion-animations
IncludedAdds production-safe Motion for React or Framer Motion animations to Next.js apps, including reveal, hover and tap micro-interactions, whileInView, stagger, AnimatePresence, layout and layoutId transitions, reorder, scroll-linked UI, and lightweight route-content transitions. Use when the user asks to add, refactor, or debug Motion or Framer Motion in App Router or Pages Router codebases, especially around server/client boundaries, reduced motion, LazyMotion, bundle size, hydration, or route transitions. Avoid for GSAP-style timelines, WebGL or 3D scenes, heavy scroll storytelling, or CSS-only effects unless Motion is explicitly requested.