add-robot
GitHub用于在EmbodiChain中新增机器人或变体时,自动脚手架生成RobotCfg子类、配置结构、注册逻辑及测试存根。支持单文件或包布局,规范了默认值构建与物理链创建协议。
Trigger Scenarios
Install
npx skills add DexForce/EmbodiChain --skill add-robot -g -y
SKILL.md
Frontmatter
{
"name": "add-robot",
"description": "Use when adding a new robot to EmbodiChain — scaffolds a RobotCfg subclass (single-file or package layout) with the _build_defaults hook, build_pk_serial_chain, registration, docs page, and test stub."
}
Add Robot
When to Use
- Adding a new robot to EmbodiChain.
- Adding a variant to an existing robot (a new version / arm kind / hand brand).
- Scaffolding a
RobotCfgsubclass.
The RobotCfg Protocol
Every robot config subclasses RobotCfg and overrides two hooks:
_build_defaults(self, init_dict=None)— read variant fields frominit_dict, set them onself, then populateurdf_cfg/control_parts/solver_cfg/joint_drive_props/attrs.build_pk_serial_chain(self, device=...)— return{control_part: pk.SerialChain}, reading the PK URDF from a single_pk_urdf_pathsource.
from_dict is a 3-line template (do not reimplement):
cfg = cls()
cfg._build_defaults(init_dict)
return merge_robot_cfg(cfg, init_dict)
to_dict / to_string / save_to_file are inherited from RobotCfg and round-trip.
Two Layouts
Concrete configs live in the extensions/embodichain_robots/ import package, bundled
with the core distribution/version. Generic robot runtime, configuration,
solvers, and composition stay in embodichain/lab/sim/.
| Layout | When | Files |
|---|---|---|
| Single-file | Variant-less robot | my_robot.py |
| Package | Robot with variants (versions / arm kinds / hand brands) | types.py, cfg.py, optional params.py/utils.py, __init__.py |
The Contract (read first)
A cfg's _build_defaults must populate:
uid(str)urdf_cfg(URDFCfg) orfpathcontrol_parts(Dict[str, List[str]]; joint names support regex)solver_cfg(Dict[str, SolverCfg]; keys matchcontrol_parts)joint_drive_props(JointDrivePropertiesCfg)attrs(RigidBodyPhysicsCfg)
Use arm / eef for default single-arm control groups and left_arm,
right_arm, left_eef, right_eef for dual-arm defaults. Add an EEF group
only when the robot has controllable end-effector joints. These names are a
convention: user-defined names remain valid, without automatic aliases or a
reserved-name validator. Keep asset component, link and joint identifiers intact.
build_pk_serial_chain must read from _pk_urdf_path (a property for
constant-path robots, a method for variant-dependent paths). The PK chain's DOF
must match the matching control_parts entry (the test stub asserts this).
Steps
-
Pick a layout using the table above. Single-file for variant-less robots; package for robots with variants.
-
Create the cfg file(s). Subclass
RobotCfg. Declare variant fields (enums) if using the package layout. -
Implement
_build_defaults(self, init_dict=None). Set variant fields frominit_dict, then populate the Contract fields. Single-file template:def _build_defaults(self, init_dict=None): init_dict = init_dict or {} self.uid = "MyRobot" self.urdf_cfg = URDFCfg(components=[...]) self.control_parts = {"arm": ["JOINT[1-6]"]} self.solver_cfg = {"arm": OPWSolverCfg(end_link_name="link6", root_link_name="base_link")} self.joint_drive_props = JointDrivePropertiesCfg(stiffness={"JOINT[1-6]": 1e4})Variant-aware template (reads version / arm_kind):
def _build_defaults(self, init_dict=None): init_dict = init_dict or {} self.version = MyRobotVersion(init_dict.get("version", "v1")) self.arm_kind = MyRobotArmKind(init_dict.get("arm_kind", "default")) ... # then urdf_cfg / control_parts / solver_cfg / joint_drive_props / attrs -
Implement
build_pk_serial_chainreading from_pk_urdf_path:@property def _pk_urdf_path(self) -> str: return get_data_path("MyRobot/arm.urdf") def build_pk_serial_chain(self, device=torch.device("cpu"), **kwargs): chain = create_pk_serial_chain( urdf_path=self._pk_urdf_path, device=device, end_link_name="link6", root_link_name="base_link", ) return {"arm": chain} -
Keep
from_dictas the 3-line template — do not reimplement it. -
Add
__all__and register the class inextensions/embodichain_robots/_catalog.py, then add its lazy export toextensions/embodichain_robots/__init__.py(_EXPORTSand__all__):# Catalog entry; importing the catalog must not import the robot module. "MyRobot": {"class_path": "embodichain_robots.my_robot:MyRobotCfg"}The main wheel already advertises this catalog through
embodichain.robots. Gym, workspace CLI, and dual-arm composition use its shared resolver. Variant defaults belong in the catalog. Concrete robots use only the canonical package; no core compatibility module or CLI class map is needed. Supply optional control metadata when known:dofcounts unique independent default control joints, excluding mimic followers;control_partsrecords raw per-part counts.mimic_jointsmaps followers to leaders, andcontrol_part_mimicsrecords follower membership by group. Overlapping groups must not inflate DOF. Declaresupports_dual_armonly for a compatible default single-arm URDF/control-part/solver contract. Families may declarevariantswith control profiles and adefault_variant; flat preset IDs usevariant_of. Keep the catalog free of robot/configuration imports. -
Add documentation: create
docs/source/resources/robot/<name>.mdand add it todocs/source/resources/robot/index.rst. -
Add a test stub with a
__main__smoke test + the DOF drift guard. Use/add-testfor full test scaffolding; the guard snippet is:chains = cfg.build_pk_serial_chain() for part, chain in chains.items(): assert len(chain.get_joint_parameter_names()) == len(cfg.control_parts[part]) -
Verify:
preview-assetCLI +RobotCfg.from_dict(cfg.to_dict())round-trip.
Reusable embodiment handoff
RobotCfg owns simulation construction, control parts, solvers, and physical
properties, plus optional mounted camera configurations in sensors.
Use robot-local parent link names and stable sensor UIDs. Standalone simulation
creates these cameras only with enable_sensor=True; Gym overrides that
switch with its environment acquisition setting. An explicit sensor list
replaces defaults and sensors: [] clears them. Keep independent cameras,
task declarations and Task Program skill profiles outside the robot class.
If the user also wants the robot selectable from task deployments, invoke
$add-embodiment-component after the robot config passes its own tests. That
component selects the robot, declares additional independent sensors, and maps stable
logical resources/endpoints/capabilities/commands into skill_profile.
Do not copy those semantic declarations into the robot class.
Common Mistakes
| Mistake | Fix |
|---|---|
all instead of __all__ |
Use __all__ — lowercase all breaks import *. |
solver_cfg set twice |
Set it once in _build_defaults only. |
| PK URDF drifts from sim URDF | Route PK through _pk_urdf_path; keep the DOF guard. |
Reimplementing from_dict |
Keep the 3-line template; put logic in _build_defaults. |
root_link_name as a tuple |
It must be a str. |
Calling a nonexistent validate |
Don't call methods that don't exist. |
Quick Reference
| Parameter | Type | Description |
|---|---|---|
uid |
str | Unique robot identifier |
urdf_cfg |
URDFCfg | URDF file and components |
control_parts |
Dict[str, List[str]] | Joint groups for control |
solver_cfg |
Dict[str, SolverCfg] | IK solver configurations |
joint_drive_props |
JointDrivePropertiesCfg | Joint drive, limits, friction, and armature |
attrs |
RigidBodyPhysicsCfg | Rigid-body physics attributes |
| variant fields | enum / str / bool | Optional subclass fields |
_pk_urdf_path |
property or method → str | URDF for the FK/IK serial chain |
File locations:
- Config:
extensions/embodichain_robots/<name>.pyorextensions/embodichain_robots/<name>/ - Catalog / lazy exports:
extensions/embodichain_robots/_catalog.py,extensions/embodichain_robots/__init__.py - Shared resolver:
embodichain/robot_registry.py - Docs:
docs/source/resources/robot/<name>.md - Tests:
tests/sim/objects/test_robot_cfg.py - Base class:
embodichain/lab/sim/cfg/robot.py(RobotCfg) - Guide:
docs/source/guides/add_robot.rst· Tutorial:docs/source/tutorial/add_robot.rst
Version History
-
6611467
Current 2026-10-19 21:36
将官方任务和机器人模块移至extensions/目录;优化挂载相机定义至机器人配置;提取机器人预设并增加CLI功能;标准化末端执行器控制部分命名。
-
6f20b06
2026-09-23 01:29
修正了字段名拼写错误:将drive_pros更正为joint_drive_props,将RigidBodyAttributesCfg更正为RigidBodyPhysicsCfg,以匹配实际协议定义。
- 12178b3 2026-08-20 11:23


