feat(skills): add taiyang servo dance skill

Add PWM-based servo control skill for RDK nodes with hardware servo support.

Changes:
- Add taiyang skill with SKILL.md and servo_dance.py script
- Update Dockerfile and Containerfile to include taiyang skill
- Update SOUL.md with skill constraints documentation

The skill controls two servos via /sys/class/pwm interface and must run on node side only.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
d-robotics 2026-04-22 15:36:54 +08:00
parent e6dab8c3dd
commit 077f2eacf1
5 changed files with 155 additions and 0 deletions

View File

@ -41,7 +41,9 @@ EOF
COPY rdk-claw/SOUL.md /app/docs/reference/templates/SOUL.md
COPY rdk-claw/IDENTITY.md /app/docs/reference/templates/IDENTITY.md
COPY rdk-claw/node-remote-connect /app/skills/node-remote-connect
COPY rdk-claw/taiyang /app/skills/taiyang
RUN chown -R 1001:1001 /app/skills/node-remote-connect
RUN chown -R 1001:1001 /app/skills/taiyang
ENV HOME=/home/user
USER 1001:1001

View File

@ -29,8 +29,12 @@ COPY IDENTITY.md /app/docs/reference/templates/IDENTITY.md
# 添加 node-remote-connect skill
COPY node-remote-connect /app/skills/node-remote-connect
# 添加 taiyang skill
COPY taiyang /app/skills/taiyang
# 确保权限正确
RUN chown -R node:node /app/skills/node-remote-connect
RUN chown -R node:node /app/skills/taiyang
USER node

View File

@ -37,3 +37,15 @@ Be the assistant you'd actually want to talk to. Concise when needed, thorough w
Each session, you wake up fresh. These files are your memory. Read them. Update them. They're how you persist.
If you change this file, tell the user — it's your soul, and they should know.
## Skills
### Taiyang! - Servo Dance
A hardware control skill that drives two servos on an RDK board via PWM signals.
**Constraints:**
- Must be executed on the Node side (the RDK board). Never run this on the cloud Gateway — there is no PWM hardware here.
- Requires PWM-capable servos physically connected to the board (`/sys/class/pwm/pwmchip0/pwm0` and `pwm1`).
When users mention "taiyang", "servo", or "servo dance", remind them this skill only works on RDK nodes with servo hardware attached.

59
rdk-claw/taiyang/SKILL.md Normal file
View File

@ -0,0 +1,59 @@
---
name: 太阳!
description: 控制 RDK 节点上的舵机挥动,让两个舵机同步或反向运动。使用 PWM 信号控制舵机角度0°-180°支持多种舞动模式。触发话太阳、舵机挥动、servo dance、PWM 舵机、双舵机控制、双舵机控制。
---
# 太阳!- 舵机挥动技能
让舵机动起来!就像太阳升起一样充满活力。
## 前置条件
- RDK 节点已连接
- PWM 接口可用(/sys/class/pwm/pwmchip0
- 两个舵机分别连接到 pwm0 和 pwm1
## 快速使用
直接调用脚本启动舵机舞动:
```bash
python3 ~/.openclaw/skills/taiyang/scripts/servo_dance.py
```
停止舞动:
```bash
pkill -f servo_dance.py
```
## 舵机控制参数
| 参数 | 默认值 | 说明 |
|------|--------|------|
| 频率 | 50Hz | 标准舵机频率20ms周期 |
| 脉宽范围 | 1-2ms | 0°-180° 对应 |
| 中心位置 | 1.5ms | 90° |
## PWM 接口路径
- pwm0: `/sys/class/pwm/pwmchip0/pwm0` → Servo 0
- pwm1: `/sys/class/pwm/pwmchip0/pwm1` → Servo 1
## 舞动模式
脚本内置三种模式循环:
1. **波浪模式** - Servo0 和 Servo1 反向运动
2. **同步模式** - 两个舵机同步运动
## 手动控制
如需手动控制单个舵机:
```bash
# 设置角度0-180
echo $((1000000 + angle * 5555)) > /sys/class/pwm/pwmchip0/pwm0/duty_cycle
```
角度计算duty = 1000000 + (angle/180) * 1000000 (单位ns)

View File

@ -0,0 +1,78 @@
#!/usr/bin/env python3
"""
太阳- 双舵机舞动脚本
让舵机像太阳升起一样充满活力地挥动
"""
import time
import os
import sys
PWM0 = "/sys/class/pwm/pwmchip0/pwm0"
PWM1 = "/sys/class/pwm/pwmchip0/pwm1"
PERIOD = 20000000 # 20ms = 50Hz
def init_pwm():
"""初始化两个PWM通道"""
for pwm in [PWM0, PWM1]:
try:
with open(os.path.join(pwm, "period"), "w") as f:
f.write(str(PERIOD))
with open(os.path.join(pwm, "duty_cycle"), "w") as f:
f.write("1500000") # 中心位置 90°
with open(os.path.join(pwm, "enable"), "w") as f:
f.write("1")
except Exception as e:
print(f"Error initializing {pwm}: {e}")
sys.exit(1)
def set_angle(pwm, angle):
"""设置舵机角度 (0-180°)"""
duty = int(1000000 + (angle / 180.0) * 1000000)
with open(os.path.join(pwm, "duty_cycle"), "w") as f:
f.write(str(duty))
def wave_pattern():
"""波浪模式:两舵机反向运动"""
for a in range(0, 181, 30):
set_angle(PWM0, a)
set_angle(PWM1, 180 - a)
time.sleep(0.2)
for a in range(180, -1, -30):
set_angle(PWM0, a)
set_angle(PWM1, 180 - a)
time.sleep(0.2)
def sync_pattern():
"""同步模式:两舵机同步运动"""
for a in [0, 90, 180, 90]:
set_angle(PWM0, a)
set_angle(PWM1, a)
time.sleep(0.3)
def stop_pwm():
"""停止PWM输出"""
set_angle(PWM0, 90)
set_angle(PWM1, 90)
time.sleep(0.3)
for pwm in [PWM0, PWM1]:
with open(os.path.join(pwm, "enable"), "w") as f:
f.write("0")
def main():
print("🌞 太阳!- 舵机舞动开始")
print("=" * 40)
init_pwm()
try:
while True:
print("🌊 波浪模式...")
wave_pattern()
print("🎯 同步模式...")
sync_pattern()
except KeyboardInterrupt:
print("\n停止舞动...")
stop_pwm()
print("🌞 太阳落山了,再见!")
if __name__ == "__main__":
main()