Files
dora_littlehand/dora_voice_control/docs/add_robot.md
2026-02-02 12:49:40 -03:00

2.7 KiB

Add a New Robot

This project uses a simple adapter + behavior pattern.

1) Create a robot adapter

Implement the common command interface:

  • File: dora_voice_control/dora_voice_control/robots/<robot_name>/adapter.py
  • Base class: RobotAdapter (dora_voice_control/dora_voice_control/core/robot.py)

Example (vacuum style):

from __future__ import annotations
from typing import Any, Dict, List

from ...core.robot import RobotAdapter
from ...core.state import RobotStep

NAME = "my_robot"
ALIASES = {"my_robot", "my_alias"}

class MyRobotAdapter(RobotAdapter):
    def grab(self) -> List[RobotStep]:
        return [RobotStep(action="vacuum_on", payload={})]

    def release(self) -> List[RobotStep]:
        return [RobotStep(action="vacuum_off", payload={})]

    def move(self, payload: Dict[str, Any]) -> List[RobotStep]:
        return [RobotStep(action="move_to_pose", payload=payload)]

    def reset_tool(self) -> List[RobotStep]:
        return [RobotStep(action="vacuum_off", payload={})]

The action strings must match what your robot node understands.

2) Create robot actions

  • File: dora_voice_control/dora_voice_control/robots/<robot_name>/actions.py
  • Use ActionInfo to define names, aliases, and requirements.
from ...core.behavior import ActionInfo

MY_ACTIONS = {
    "tomar": ActionInfo(name="tomar", aliases=["toma"], requires_object=False),
    "soltar": ActionInfo(name="soltar", aliases=["suelta"], requires_object=False),
}

3) Create robot behavior

  • File: dora_voice_control/dora_voice_control/robots/<robot_name>/behavior.py
  • Subclass RobotBehavior and implement action_handlers().
from typing import Callable
from ...core.behavior import ActionContext, RobotBehavior
from .actions import MY_ACTIONS

class MyRobotBehavior(RobotBehavior):
    ACTIONS = MY_ACTIONS

    def action_tomar(self, ctx: ActionContext) -> bool:
        self._queue_steps(ctx, self.robot_adapter.grab())
        return True

    def action_soltar(self, ctx: ActionContext) -> bool:
        self._queue_steps(ctx, self.robot_adapter.release())
        return True

    def action_handlers(self) -> dict[str, Callable[[ActionContext], bool]]:
        return {
            "tomar": self.action_tomar,
            "soltar": self.action_soltar,
        }

4) Register the robot

  • File: dora_voice_control/dora_voice_control/robots/__init__.py

Add a resolver entry that maps ROBOT_TYPE to your adapter/behavior.

5) Update dataflow

Set ROBOT_TYPE in your dataflow:

env:
  ROBOT_TYPE: "my_robot"

Safety notes

  • Keep bounds checks in behavior methods (_queue_move already checks workspace limits).
  • For real hardware, validate with a staged plan: simulation → dry-run → full run.