SunFounder PiCrawler Kit
  • About this Kit
  • 组装视频
  • 玩转 Python
    • 1. Python 快速入门指南
    • 2. Python 实践项目
      • 1. 移动
      • 2. 键盘控制
      • 3. 音效功能
      • 4. 避障功能
      • 5. 计算机视觉
      • 6. 录制视频
      • 7. 斗牛
      • 8. 寻宝游戏
      • 9. 姿态
      • 10. 调整姿态
      • 11. 记录新动作
      • 12. 扭动舞
      • 13. 情感机器人
      • 14. 动作展示
  • 看 · 听 · 响应 — 多 LLM 驱动的 AI 交互
  • 畅玩 EzBlock
  • 舵机归零以便组装
  • 使用 GPT-4O 的 AI 交互
  • 附录
  • 硬件
  • FAQ
SunFounder PiCrawler Kit
  • 玩转 Python
  • 14. 动作展示
  • 查看页面源码

14. 动作展示

本示例提供一个交互式菜单,可触发 PiCrawler 的多种预编程动作,包括挥手、 握手、战斗、点头、俯卧撑等。

运行代码

cd ~/picrawler/examples
sudo python3 14_action_gallery.py

运行后,终端会打印编号的动作列表。输入动作编号并按 Enter 即可执行。 再次按 Enter 可重复上一个动作。按 Ctrl+C 安全退出,机器人返回坐姿。

代码

备注

您可以**修改/重置/复制/运行/停止**以下代码。但在此之前,您需要进入源代码 路径,如 picrawler\examples。修改代码后,可以直接运行以查看效果。

from time import sleep

BODY_LENGTH = 77
BODY_WIDTH = 77
BODY_DIAGONAL = 108.9
DELTA = 45


def sit(spider):
    spider.do_action('sit', speed=40)


def stand(spider):
    spider.do_action('stand', speed=40)


def look_up(spider):
    coords = [
        [[45, 45, -50], [45, 0, -50], [45, 0, -50], [45, 45, -50]],
        [[45, 45, -76], [45, 0, -76], [45, 0, -38], [45, 45, -30]],
    ]
    for coord in coords:
        spider.do_step(coord, 60)


def look_down(spider):
    coords = [
        [[45, 45, -50], [45, 0, -50], [45, 0, -50], [45, 45, -50]],
        [[45, 45, -28], [45, 0, -40], [45, 0, -68], [45, 45, -76]],
    ]
    for coord in coords:
        spider.do_step(coord, 60)


def dance(spider):
    spider.do_action('dance', speed=60)


def wave_hand(spider):
    coords = [
        [[45, 45, -50], [45, 0, -50], [45, 0, -50], [45, 45, -50]],
        [[45, 45, -70], [60, 0, 120], [45, 0, -60], [45, 45, -30]],
        [[45, 45, -70], [-20, 60, 120], [45, 0, -60], [45, 45, -30]],
        [[45, 45, -70], [60, 0, 120], [45, 0, -60], [45, 45, -30]],
        [[45, 45, -70], [-20, 60, 120], [45, 0, -60], [45, 45, -30]],
        [[45, 45, -50], [45, 0, -30], [45, 0, -50], [45, 45, -50]],
        [[45, 45, -50], [45, 0, -40], [45, 0, -50], [45, 45, -50]],
        [[45, 45, -50], [45, 0, -50], [45, 0, -50], [45, 45, -50]],
    ]
    for coord in coords:
        spider.do_step(coord, 58)


def shake_hand(spider):
    coords = [
        [[45, 45, -50], [45, 0, -50], [45, 0, -50], [45, 45, -50]],
        [[45, 45, -65], [5, 280, 80], [45, 0, -60], [45, 45, -40]],
        [[45, 45, -65], [5, 280, 100], [45, 0, -60], [45, 45, -40]],
        [[45, 45, -65], [5, 280, -10], [45, 0, -60], [45, 45, -40]],
        [[45, 45, -65], [5, 280, 100], [45, 0, -60], [45, 45, -40]],
        [[45, 45, -65], [5, 280, -10], [45, 0, -60], [45, 45, -40]],
        [[45, 45, -65], [5, 280, 100], [45, 0, -60], [45, 45, -40]],
        [[45, 45, -65], [5, 280, -10], [45, 0, -60], [45, 45, -40]],
        [[45, 45, -65], [5, 100, 10], [45, 0, -60], [45, 45, -40]],
        [[45, 45, -65], [5, 100, 10], [45, 0, -60], [45, 45, -40]],
        [[45, 45, -50], [45, 0, -30], [45, 0, -50], [45, 45, -50]],
        [[45, 45, -50], [45, 0, -40], [45, 0, -50], [45, 45, -50]],
        [[45, 45, -50], [45, 0, -50], [45, 0, -50], [45, 45, -50]],
    ]
    for coord in coords:
        spider.do_step(coord, 52)


def fighting(spider):
    ready = [
        [[45, 45, -50], [45, 0, -50], [45, 0, -50], [45, 45, -50]],
        [[45, 45, -40], [45, 0, -40], [50, 20, -20], [45, 45, -50]],
        [[45, 45, -40], [45, 0, -40], [40, 20, -45], [45, 45, -50]],
        [[45, 45, -40], [45, 0, -40], [60, 40, -60], [45, 45, -40]],
        [[45, 45, -40], [45, 30, -30], [60, 40, -60], [45, 45, -40]],
        [[45, 45, -30], [45, 30, -30], [60, 40, -60], [60, 40, -60]],
    ]
    twist_butt = [
        [[55, 7, -30], [19, 48, -30], [77, 12, -60], [36, 63, -60]],
        [[19, 48, -30], [55, 7, -30], [36, 63, -60], [77, 12, -60]],
        [[55, 7, -30], [19, 48, -30], [77, 12, -60], [36, 63, -60]],
        [[19, 48, -30], [55, 7, -30], [36, 63, -60], [77, 12, -60]],
        [[40, 30, -30], [40, 30, -30], [60, 40, -60], [60, 40, -60]],
        [[40, 50, -30], [40, 50, -30], [60, 20, -60], [60, 20, -60]],
    ]
    pounce_bite = [
        [[40, 40, -60], [20, 60, 110], [60, 60, -60], [60, 60, -60]],
        [[40, 40, -40], [20, 30, -40], [60, 60, -60], [60, 60, -60]],
        [[20, 60, 110], [20, 30, -60], [60, 60, -60], [60, 60, -60]],
        [[20, 30, -40], [20, 30, -40], [60, 60, -60], [60, 60, -60]],
    ]
    return_stand = [
        [[45, 45, -50], [45, 0, -30], [45, 0, -50], [45, 45, -50]],
        [[45, 45, -50], [45, 0, -40], [45, 0, -50], [45, 45, -50]],
        [[45, 45, -50], [45, 0, -50], [45, 0, -50], [45, 45, -50]],
    ]
    for coord in ready: spider.do_step(coord, 50)
    for coord in twist_butt: spider.do_step(coord, 52)
    sleep(0.2)
    for coord in pounce_bite: spider.do_step(coord, 40); sleep(0.1)
    sleep(1)
    for coord in return_stand: spider.do_step(coord, 52)


def excited(spider):
    coords = [
        [[45, 45, -50], [45, 0, -50], [45, 0, -50], [45, 45, -50]],
        [[45, 45, -30], [45, 0, -30], [45, 0, -30], [45, 45, -30]],
        [[45, 45, -80], [45, 0, -80], [45, 0, -80], [45, 45, -80]],
        [[45, 45, -30], [45, 0, -30], [45, 0, -30], [45, 45, -30]],
        [[45, 45, -80], [45, 0, -80], [45, 0, -80], [45, 45, -80]],
        [[45, 45, -30], [45, 0, -30], [45, 0, -30], [45, 45, -30]],
        [[45, 45, -80], [45, 0, -80], [45, 0, -80], [45, 45, -80]],
        [[45, 45, -50], [45, 0, -50], [45, 0, -50], [45, 45, -50]],
    ]
    for coord in coords:
        spider.do_step(coord, 40); sleep(0.08)


def play_dead(spider):
    sit = [
        [[45, 45, -50], [45, 0, -50], [45, 0, -50], [45, 45, -50]],
        [[45, 45, -10], [45, 0, -10], [45, 0, -10], [45, 45, -10]],
    ]
    play_dead = [
        [[45, 45, 100], [45, 45, 100], [45, 45, 100], [45, 45, 100]],
        [[45, 35, 60], [35, 45, 80], [35, 45, 80], [45, 35, 60]],
        [[35, 45, 80], [45, 35, 60], [45, 35, 60], [35, 45, 80]],
        [[45, 35, 60], [35, 45, 80], [35, 45, 80], [45, 35, 60]],
        [[35, 45, 80], [45, 35, 60], [45, 35, 60], [35, 45, 80]],
        [[45, 35, 60], [35, 45, 80], [35, 45, 80], [45, 35, 60]],
        [[35, 45, 80], [45, 35, 60], [45, 35, 60], [35, 45, 80]],
        [[45, 35, 60], [35, 45, 80], [35, 45, 80], [45, 35, 60]],
        [[35, 45, 80], [45, 35, 60], [45, 35, 60], [35, 45, 80]],
        [[45, 35, 60], [35, 45, 80], [35, 45, 80], [45, 35, 60]],
        [[35, 45, 80], [45, 35, 60], [45, 35, 60], [35, 45, 80]],
        [[45, 45, 100], [45, 45, 100], [45, 45, 100], [45, 45, 100]],
    ]
    return_stand = [[[45, 45, -50], [45, 0, -50], [45, 0, -50], [45, 45, -50]]]
    for coord in sit: spider.do_step(coord, 60)
    for coord in play_dead: spider.do_step(coord, 55)
    for coord in return_stand: spider.do_step(coord, 60)


def nod(spider):
    stand = [[[45, 45, -50], [45, 0, -50], [45, 0, -50], [45, 45, -50]]]
    nod = [
        [[45, 45, -80], [45, 0, -50], [45, 0, -20], [45, 45, -30]],
        [[45, 45, -20], [45, 0, -36], [45, 20, -52], [40, 20, -80]],
        [[45, 45, -80], [45, 0, -50], [45, 0, -20], [45, 45, -30]],
        [[45, 45, -20], [45, 0, -36], [45, 20, -52], [40, 20, -80]],
        [[45, 45, -80], [45, 0, -50], [45, 0, -20], [45, 45, -30]],
    ]
    return_stand = [
        [[45, 45, -80], [45, 0, -50], [45, 0, -40], [45, 45, -40]],
        [[45, 45, -60], [45, 0, -50], [45, 0, -40], [45, 45, -40]],
        [[45, 45, -50], [45, 0, -50], [45, 0, -50], [45, 45, -50]],
    ]
    for coord in stand: spider.do_step(coord, 60)
    for coord in nod: spider.do_step(coord, 45)
    sleep(.2)
    for coord in return_stand: spider.do_step(coord, 50); sleep(1)


def shake_head(spider):
    ready = [
        [[45, 45, -50], [45, 0, -50], [45, 20, -50], [45, 45, -50]],
        [[45, 45, -50], [45, 20, -30], [45, 20, -50], [45, 45, -50]],
        [[45, 45, -50], [45, 45, -50], [45, 20, -50], [45, 45, -50]],
    ]
    twist_butt = [
        [[55, 7, -50], [19, 48, -50], [77, 12, -50], [36, 63, -50]],
        [[19, 48, -50], [55, 7, -50], [36, 63, -50], [77, 12, -50]],
        [[51, 15, -50], [27, 43, -50], [72, 22, -50], [45, 56, -50]],
        [[27, 43, -50], [51, 15, -50], [45, 56, -50], [72, 22, -50]],
        [[45, 45, -50], [45, 45, -50], [45, 45, -50], [45, 45, -50]],
    ]
    return_stand = [
        [[45, 45, -50], [45, 20, -30], [45, 0, -50], [45, 45, -50]],
        [[45, 45, -50], [45, 0, -50], [45, 0, -50], [45, 45, -50]],
    ]
    for coord in ready: spider.do_step(coord, 50)
    for coord in twist_butt: spider.do_step(coord, 58)
    sleep(.5)
    for coord in return_stand: spider.do_step(coord, 52)


def look_left(spider):
    stand = [[[45, 45, -50], [45, 0, -50], [45, 0, -50], [45, 45, -50]]]
    look_left = [
        [[45, 0, -50], [45, 45, -50], [45, 45, -50], [45, 0, -50]],
        [[0, 45, -50], [45, 45, -50], [45, 45, -50], [45, 0, -50]],
        [[0, 45, -50], [45, 45, -35], [45, 45, -50], [45, 0, -50]],
        [[45, 45, -50], [45, 0, -50], [45, 0, -50], [45, 45, -50]],
    ]
    for coord in stand: spider.do_step(coord, 50)
    for coord in look_left: spider.do_step(coord, 50)


def look_right(spider):
    stand = [[[45, 45, -50], [45, 0, -50], [45, 0, -50], [45, 45, -50]]]
    look_right = [
        [[45, 45, -50], [45, 0, -50], [45, 0, -50], [45, 45, -50]],
        [[45, 45, -50], [0, 45, -50], [45, 0, -50], [45, 45, -50]],
        [[45, 45, -35], [0, 45, -50], [45, 0, -50], [45, 45, -50]],
        [[45, 0, -50], [45, 45, -50], [45, 45, -50], [45, 0, -50]],
    ]
    for coord in stand: spider.do_step(coord, 50)
    for coord in look_right: spider.do_step(coord, 50)


def warm_up(spider):
    stand = [
        [[45, 45, -50], [45, 0, -50], [45, 0, -50], [45, 45, -50]],
        [[45, 45, -50], [45, 45, -50], [45, 45, -50], [45, 45, -50]],
    ]
    left_right = [
        [[45, 37, -85], [45, 37, -14], [45, 37, -14], [45, 37, -85]],
        [[45, 45, -50], [45, 45, -50], [45, 45, -50], [45, 45, -50]],
        [[45, 37, -85], [45, 37, -14], [45, 37, -14], [45, 37, -85]],
        [[45, 45, -50], [45, 45, -50], [45, 45, -50], [45, 45, -50]],
        [[45, 37, -14], [45, 37, -85], [45, 37, -85], [45, 37, -14]],
        [[45, 45, -50], [45, 45, -50], [45, 45, -50], [45, 45, -50]],
        [[45, 37, -14], [45, 37, -85], [45, 37, -85], [45, 37, -14]],
        [[45, 45, -50], [45, 45, -50], [45, 45, -50], [45, 45, -50]],
    ]
    clockwise = []
    clockwise.append(spider.move_list.move_body_absolute(0, 25, 10))
    clockwise.append(spider.move_list.move_body_absolute(12.5, 21.65, 10))
    clockwise.append(spider.move_list.move_body_absolute(21.65, 12.5, 10))
    clockwise.append(spider.move_list.move_body_absolute(25, 0, 10))
    clockwise.append(spider.move_list.move_body_absolute(21.65, -12.5, 10))
    clockwise.append(spider.move_list.move_body_absolute(12.5, -21.65, 10))
    clockwise.append(spider.move_list.move_body_absolute(0, -25, 10))
    clockwise.append(spider.move_list.move_body_absolute(-12.5, -21.65, 10))
    clockwise.append(spider.move_list.move_body_absolute(-21.65, -12.5, 10))
    clockwise.append(spider.move_list.move_body_absolute(-25, 0, 10))
    clockwise.append(spider.move_list.move_body_absolute(-21.65, 12.5, 10))
    clockwise.append(spider.move_list.move_body_absolute(-12.5, 21.65, 10))
    clockwise.append(spider.move_list.move_body_absolute(0, 25, 10))

    anticlockwise = []
    anticlockwise.append(spider.move_list.move_body_absolute(0, 25, 10))
    anticlockwise.append(spider.move_list.move_body_absolute(-12.5, 21.65, 10))
    anticlockwise.append(spider.move_list.move_body_absolute(-21.65, 12.5, 10))
    anticlockwise.append(spider.move_list.move_body_absolute(-25, 0, 10))
    anticlockwise.append(spider.move_list.move_body_absolute(-21.65, -12.5, 10))
    anticlockwise.append(spider.move_list.move_body_absolute(-12.5, -21.65, 10))
    anticlockwise.append(spider.move_list.move_body_absolute(0, -25, 10))
    anticlockwise.append(spider.move_list.move_body_absolute(12.5, -21.65, 10))
    anticlockwise.append(spider.move_list.move_body_absolute(21.65, -12.5, 10))
    anticlockwise.append(spider.move_list.move_body_absolute(25, 0, 10))
    anticlockwise.append(spider.move_list.move_body_absolute(21.65, 12.5, 10))
    anticlockwise.append(spider.move_list.move_body_absolute(12.5, 21.65, 10))
    anticlockwise.append(spider.move_list.move_body_absolute(0, 25, 10))

    return_stand = [
        [[45, 45, -50], [45, 45, -40], [45, 0, -50], [45, 45, -50]],
        [[45, 45, -50], [45, 0, -50], [45, 0, -50], [45, 45, -50]],
    ]
    for coord in stand: spider.do_step(coord, 50)
    sleep(0.5)
    for coord in left_right: spider.do_step(coord, 48)
    sleep(.3)
    for coord in clockwise: spider.do_step(coord, 58)
    sleep(.3)
    for coord in anticlockwise: spider.do_step(coord, 58)
    sleep(.3)
    for coord in return_stand: spider.do_step(coord, 50)


def push_up(spider):
    ready = [
        [[45, 45, -50], [45, 0, -50], [45, 0, -50], [45, 45, -50]],
        [[60, 10, -60], [60, 0, -60], [20, 60, 10], [10, 65, -40]],
        [[70, 0, -76], [70, 0, -76], [0, 130, -40], [0, 130, -40]],
    ]
    push_up = [
        [[70, 0, -40], [70, 0, -40], [0, 130, -40], [0, 130, -40]],
        [[70, 0, -76], [70, 0, -76], [0, 130, -40], [0, 130, -40]],
        [[70, 0, -40], [70, 0, -40], [0, 130, -40], [0, 130, -40]],
        [[70, 0, -76], [70, 0, -76], [0, 130, -40], [0, 130, -40]],
        [[70, 0, -40], [70, 0, -40], [0, 130, -40], [0, 130, -40]],
        [[70, 0, -76], [70, 0, -76], [0, 130, -40], [0, 130, -40]],
    ]
    for coord in ready: spider.do_step(coord,70)
    for coord in push_up: spider.do_step(coord, 35); sleep(0.1)


actions_dict = {
    "sit": sit, "stand": stand, "wave_hand": wave_hand,
    "shake_hand": shake_hand, "fighting": fighting, "excited": excited,
    "play_dead": play_dead, "nod": nod, "shake_head": shake_head,
    "look_left": look_left, "look_right": look_right,
    "look_up": look_up, "look_down": look_down,
    "warm_up": warm_up, "push_up": push_up,
}

if __name__ == "__main__":
    from picrawler import Picrawler
    my_spider = Picrawler()
    actions = list(actions_dict.keys())
    for i, key in enumerate(actions): print(f'{i} {key}')
    last_key = None
    try:
        while True:
            key = input()
            if key == '':
                print(actions[last_key])
                actions_dict[actions[last_key]](my_spider)
            else:
                key = int(key)
                if key > (len(actions) - 1): print("无效按键")
                else:
                    last_key = key
                    print(actions[key])
                    actions_dict[actions[key]](my_spider)
    except KeyboardInterrupt: pass
    except Exception as e: print(f'Error:\n {e}')
    finally:
        my_spider.do_action("sit", speed=40); sleep(.1)

工作原理

  1. 程序启动时构建可用动作字典并打印编号菜单。

    actions_dict = {"sit": sit, "stand": stand, ...}
    for i, key in enumerate(actions): print(f'{i} {key}')
    
  2. 交互式菜单循环

    输入编号选择并执行动作,按 Enter 重复上一个动作,按 Ctrl+C 退出。

  3. 什么是坐标步?

    每个姿态定义为四条腿坐标的列表:[[x, y, z], ...],对应右前腿(0)、 左前腿(1)、左后腿(2)、右后腿(3)。X 为前后,Y 为左右,Z 为上下(越负越高)。

  4. 播放姿态序列 — do_step() 平滑插值舵机从当前姿态到目标姿态。速度参数 从 40(慢)到 80(快)。

  5. 内置 vs 自定义动作 — do_action() 使用内置动作,do_step() 手动构建 姿态。

  6. 添加延迟 — sleep() 在运动阶段之间插入暂停,让每个阶段视觉上完成。

  7. move_body_absolute() 循环运动 — 通过正弦/余弦值在圆上步进,执行圆形 身体摇摆。

  8. 安全退出 — finally 块确保无论程序如何退出,机器人都会返回安全的坐姿。

上一页 下一页

© 版权所有 2026, SunFounder。

利用 Sphinx 构建,使用的 主题 由 Read the Docs 开发.