-
Notifications
You must be signed in to change notification settings - Fork 12
Hands On Custom Transition
konodoki edited this page Jul 24, 2026
·
13 revisions
Transition 负责在状态切换期间临时生成电机帧。需要它是因为源状态和目标状态的 qpos/kp/kd 不一定连续,直接切换可能造成突跳;内置过渡可以保持、渐增增益或混合两个运行状态。
当这些内置策略无法表达业务需要的切换过程时,才需要自定义 Transition。本课为 com.example.sin_wave 增加 pose_gain_blend,平滑混合过渡开始帧和目标进入帧。
mods/com.example.sin_wave/pose_gain_blend.py
from collections.abc import Mapping
from bxi_example_py_elf3.utils.transition_core import (
ConfigReader,
MotorFrame,
SingleClassTransition,
require_entry_frame_provider,
)
class PoseGainBlendTransition(SingleClassTransition):
type_name = "com.example.sin_wave.pose_gain_blend"
def __init__(self, name, duration, curve):
super().__init__(name, duration)
self._curve = curve
self._start = None
self._target = None
@classmethod
def from_config(cls, name: str, raw: Mapping[str, object]):
reader = ConfigReader(raw, name)
duration = reader.float("duration", minimum=0.0)
curve = reader.literal(
"curve", ("linear", "smoothstep"), default="smoothstep"
)
reader.finish()
return cls(name, duration, curve)
def validate_states(self, from_state, to_state):
require_entry_frame_provider(to_state)
def on_start(self, ctx, from_state, to_state):
self._start = MotorFrame.create(ctx.pos_last, ctx.kp_last, ctx.kd_last)
self._target = require_entry_frame_provider(to_state).get_entry_frame(ctx)
def apply(self, ctx, dt, progress):
if self._start is None or self._target is None:
raise RuntimeError("pose gain blend has not started")
alpha = progress
if self._curve == "smoothstep":
alpha = progress * progress * (3.0 - 2.0 * progress)
ctx.set_motor_target(
self._start.qpos + (self._target.qpos - self._start.qpos) * alpha,
self._start.kp + (self._target.kp - self._start.kp) * alpha,
self._start.kd + (self._target.kd - self._start.kd) * alpha,
)在 plugin.py 顶层添加:
from . import pose_gain_blend # noqa: F401无需修改框架注册表。
class SinWaveState(RobotControlState, EntryFrameProvider):
def get_entry_frame(self, ctx):
return self._motor_frame(
ctx.joint_nominal_pos, ctx.joint_kp, ctx.joint_kd
)transition_profiles:
pose_blend:
type: com.example.sin_wave.pose_gain_blend
duration: 0.5
curve: smoothstep
routes:
- from: com.bxi.basic_actions/normal
event: activate
to: sin_wave
transition: pose_blend单次覆盖:
transition:
profile: pose_blend
duration: 1.0
curve: linear启用热重载后修改插件,日志应显示整个 ModRuntime 重建成功。常见错误:
-
unknown transition type:plugin.py没导入模块。 -
duplicate transition type:名称未包含唯一 Mod 命名空间。 -
unknown fields:字段未被 reader 消费。 -
must implement EntryFrameProvider:某条目标边能力不足。
下一课:双状态运行混合。