diff --git a/Dockerfile b/Dockerfile index 35f88da..05f3da0 100644 --- a/Dockerfile +++ b/Dockerfile @@ -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 diff --git a/rdk-claw/Containerfile b/rdk-claw/Containerfile index 4cbd997..f0ca7be 100644 --- a/rdk-claw/Containerfile +++ b/rdk-claw/Containerfile @@ -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 diff --git a/rdk-claw/SOUL.md b/rdk-claw/SOUL.md index 7f725b2..c0e635b 100644 --- a/rdk-claw/SOUL.md +++ b/rdk-claw/SOUL.md @@ -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. diff --git a/rdk-claw/taiyang/SKILL.md b/rdk-claw/taiyang/SKILL.md new file mode 100644 index 0000000..3238da7 --- /dev/null +++ b/rdk-claw/taiyang/SKILL.md @@ -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) diff --git a/rdk-claw/taiyang/scripts/servo_dance.py b/rdk-claw/taiyang/scripts/servo_dance.py new file mode 100644 index 0000000..3baaada --- /dev/null +++ b/rdk-claw/taiyang/scripts/servo_dance.py @@ -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()