원클릭으로
add-functor
Use when adding a new observation, event, reward, action, dataset, or randomization functor to an EmbodiChain environment
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
메뉴
Use when adding a new observation, event, reward, action, dataset, or randomization functor to an EmbodiChain environment
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
SOC 직업 분류 기준
Use when writing tests for EmbodiChain modules, including observation functors, reward functors, solvers, sensors, environments, or any Python module
Use when adding a new simulation atomic action or motion primitive to EmbodiChain's AtomicActionEngine.
Use when a request asks to reference, refresh, write, or register project development context so the agent resolves the topic through agent_context/MAP.yaml and reads or updates the mapped Markdown context files.
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.
Claude adapter for the canonical EmbodiChain add-robot skill.
Claude adapter for the canonical EmbodiChain release skill.
| name | add-functor |
| description | Use when adding a new observation, event, reward, action, dataset, or randomization functor to an EmbodiChain environment |
Scaffold a new functor following EmbodiChain's Functor/FunctorCfg pattern.
| Functor Type | Config Class | Module File | Manager | Signature |
|---|---|---|---|---|
| Observation | ObservationCfg (extends FunctorCfg) | managers/observations.py | ObservationManager | (env, obs, entity_cfg, ...) -> Tensor |
| Reward | RewardCfg (extends FunctorCfg) | managers/rewards.py | RewardManager | (env, obs, action, info, ...) -> Tensor |
| Event | EventCfg (extends FunctorCfg) | managers/events.py | EventManager | (env, env_ids, ...) -> None |
| Action | ActionTermCfg (extends FunctorCfg) | managers/actions.py | ActionManager | Varies |
| Dataset | DatasetFunctorCfg (extends FunctorCfg) | managers/datasets.py | DatasetManager | (env, ...) -> dict |
| Randomization | EventCfg (randomizations ARE events) | managers/randomization/<type>.py | EventManager | (env, env_ids, entity_cfg, ...) -> None |
A plain function with the right signature. Registered via FunctorCfg(func=my_function, params={...}).
def my_reward(
env: EmbodiedEnv,
obs: dict,
action: EnvAction,
info: dict,
my_param: float = 1.0, # params become keyword args
) -> torch.Tensor:
"""Short one-line summary.
Longer description if needed.
Args:
env: The environment instance.
obs: The observation dictionary.
action: The action taken.
info: The info dictionary.
my_param: Description of this parameter.
Returns:
Reward tensor of shape (num_envs,).
"""
# implementation
return result
A class inheriting Functor, with __init__(cfg, env) and __call__(env, ...). Registered via FunctorCfg(func=MyClass, params={...}).
class my_randomizer(Functor):
"""One-line summary."""
def __init__(self, cfg: FunctorCfg, env: EmbodiedEnv):
super().__init__(cfg, env)
# Extract params and initialize state
self.entity_cfg: SceneEntityCfg = cfg.params["entity_cfg"]
def __call__(self, env: EmbodiedEnv, env_ids: torch.Tensor, **kwargs):
"""Apply the randomization.
Args:
env: The environment instance.
env_ids: Target environment IDs.
"""
# implementation
Ask the user:
Place the functor in the existing module for its type:
| Type | File |
|---|---|
| Observation | embodichain/lab/gym/envs/managers/observations.py |
| Reward | embodichain/lab/gym/envs/managers/rewards.py |
| Event | embodichain/lab/gym/envs/managers/events.py |
| Action | embodichain/lab/gym/envs/managers/actions.py |
| Dataset | embodichain/lab/gym/envs/managers/datasets.py |
| Physics randomization | embodichain/lab/gym/envs/managers/randomization/physics.py |
| Visual randomization | embodichain/lab/gym/envs/managers/randomization/visual.py |
| Spatial randomization | embodichain/lab/gym/envs/managers/randomization/spatial.py |
| Geometry randomization | embodichain/lab/gym/envs/managers/randomization/geometry.py |
Follow the template for function-style or class-style (see above).
Key rules:
env: EmbodiedEnv (use TYPE_CHECKING guard for the import)from __future__ import annotations at the topSceneEntityCfg for entity references, not raw stringsshape key to FunctorCfg.extra dictenv_ids: torch.Tensor | list[int](num_envs,)__all__Add the new functor to the module's __all__ list. If no __all__ exists, create one.
Place at tests/gym/envs/managers/test_<functor_type>.py (append to existing file if present).
For functors that don't need a live simulation, use mock objects (MockEnv, MockSim, etc.) following the pattern in tests/gym/envs/managers/test_reward_functors.py.
blackblack embodichain/lab/gym/envs/managers/<module>.py
black tests/gym/envs/managers/test_<functor_type>.py
| Mistake | Fix |
|---|---|
| Wrong first argument signature | Observation: (env, obs, ...), Reward: (env, obs, action, info, ...), Event/Randomization: (env, env_ids, ...) |
Importing EmbodiedEnv at module level | Use TYPE_CHECKING guard to avoid circular imports |
Forgetting SceneEntityCfg for entity refs | Always use SceneEntityCfg(uid="...") not bare strings |
| Returning wrong tensor shape | Rewards must return (num_envs,), observations must match declared shape |
Missing from __future__ import annotations | Required in every file |
Class-style functor not calling super().__init__ | Always call super().__init__(cfg, env) |
| Adding randomizer as standalone | Randomizations ARE events — they go in randomization/ but use EventCfg |
| Step | Action |
|---|---|
| 1 | Identify manager type + function vs class style |
| 2 | Write functor in the correct module file |
| 3 | Update __all__ in that module |
| 4 | Write test with mocks (no sim needed for most) |
| 5 | Run black on changed files |