新浪科技

玩转PiPER | 机械臂固定点位录制与播放功能实现

市场资讯 2025.08.08 16:53

(来源:AGV网)

本文基于松灵PIPER机械臂实现了固定点位录制与播放功能。通过对Python SDK的应用,可以实现机械臂特定位置的记录和重复执行,为教学演示和自动化操作提供了强有力的技术支撑。

本文将分析代码实现细节,并提供完整代码、使用指南和步骤演示。

代码仓库

Github链:https://github.com/agilexrobotics/Agilex-College.git

【功能展示】

一、使用前准备

1.1. PIPER 机械臂硬件准备

  • 工作空间内无障碍物,为机械臂提供充足的运动空间

  • 确认机械臂电源正常,所有指示灯显示正常状态

  • 照明条件良好,便于观察机械臂位置和状态

  • 如果配备夹爪,检查夹爪动作是否正常

  • 地面平稳,避免振动影响录制精度

  • 验证示教按钮功能正常

1.2.环境配置

  • 操作系统:Ubuntu(推荐Ubuntu 18.04或更高版本)

  • Python环境:Python 3.6或更高版本

  • git代码管理工具:用于克隆远程的代码仓库

sudo apt install git
  • pip包管理器:用于安装Python依赖包

sudo apt install python3-pip
  • 安装CAN工具

sudo apt install can-utils ethtool
  • 安装官方提供的Python SDK包,其中1_0_0_beta是带API的版本

git clone -b 1_0_0_beta https://github.com/agilexrobotics/piper_sdk.gitcd piper_sdkpip3 install .

参考文档:

https://github.com/agilexrobotics/piper_sdk/blob/1_0_0_beta/README(ZH).MD

二、固定点位录制与播放功能操作步骤

  • 机械臂上电,将USB转CAN模块与电脑连接(确保只连接一个CAN模块)

  • 打开终端,激活CAN模块

sudo ip link set can0 up type can bitrate 1000000
  • 克隆远程代码仓库

git clone https://github.com/agilexrobotics/Agilex-College.git
  • 切换至recordAndPlayPos目录

cd Agilex-College/piper/recordAndPlayPos/
  • 运行录制程序

python3 recordPos.py
  • 短按示教按钮进入示教模式

  • 摆放好机械臂的位置,终端回车进行点位的录制,输入'q'可结束录制

  • 录制结束后,再次短按示教按钮退出示教模式

  • 播放前须知:初次退出示教模式时,需要经过特定的初始化过程才能从示教模式切换到CAN模式,因此播放程序会自动执行复位操作,将2、3、5号关节回到安全位置(零点),防止机械臂在重力作用下突然下落造成损坏,在特殊情况下需要人工辅助2、3、5关节回到零点

  • 运行播放程序

python3 playPos.py
  • 使能成功后,终端回车即可播放点位

三、过程中遇到的问题及解决方法

没有Piper类。

原因:当前安装的SDK不是带API的版本。

解决方法:执行pip3 uninstall piper_sdk卸载当前的SDK,然后按照1.2.环境配置的方法安装1_0_0_beta版本的SDK。

机械臂不动,终端输出如下。

原因:程序运行过程中,短按了示教按钮。

解决方法:检查示教按钮的指示灯是否处于熄灭状态,如果是重新运行程序即可,不是则需先短按示教按钮退出示教模式再运行程序。

四、实现代码/原理解读与参数说明

4.1. 点位录制程序的实现

点位录制程序是系统的数据采集模块,负责在示教模式下捕获机械臂的关节位置信息。

4.1.1. 程序初始化与配置

4.1.1.1. 参数配置设计

# 是否有夹爪have_gripper = True# 示教模式检测超时时间,单位:秒timeout = 10.0# 保存点位的CSV文件路径CSV_path = os.path.join(os.path.dirname(__file__), "pos.csv")

配置参数分析:

have_gripper参数类型为布尔类型,True时代表有夹爪。

timeout参数为设定示教模式检测超时时间,启动程序后,如果10s没有进入示教模式,程序会退出。

CSV_path参数为设定轨迹文件保存路径,默认为与程序当前同路径,文件名为pos.csv

4.1.1.2. 机械臂连接与初始化

# 初始化并连接机械臂piper = Piper("can0")interface = piper.init()piper.connect()time.sleep(0.1)

连接机制分析:

Piper()是API的核心类,该类在interface的基础上简化了通用的一些方法。

init()会创建并返回interface实例,可用于调用Piper的一些特殊方法。

connect()会开启一个线程来连接CAN端口以及处理CAN数据。

time.sleep(0.1)的添加是为了确保连接完全建立。在嵌入式系统中,硬件初始化通常需要一定的时间,这个短暂的延时确保了后续操作的可靠性。

4.1.2. 位置获取与数据存储

4.1.2.1. 位置获取函数实现

def get_pos():    '''获取机械臂当前关节弧度和夹爪张开距离'''    joint_state = piper.get_joint_states()[0]    if have_gripper:        return joint_state + (piper.get_gripper_states()[0][0], )    return joint_state

4.1.2.2. 模式检测与切换

print("INFO: 请点击示教按钮进入示教模式")over_time = time.time() + timeoutwhile interface.GetArmStatus().arm_status.ctrl_mode != 2:    if over_time < time.time():        print("ERROR: 示教模式检测超时,请检查示教模式是否开启")        exit()    time.sleep(0.01)

状态轮询策略:程序采用轮询方式检测控制模式,这种方法的特点:

  • 实现简单,逻辑清晰

  • 对系统资源要求较低

超时保护机制:10秒的超时设置考虑了实际操作的需要:

  • 用户理解提示信息的时间

  • 找到并按下示教按钮的时间

  • 系统响应和状态切换的时间

  • 异常情况下的容错处理

示教模式的安全特性:

  • 关节力矩释放,允许手动操作

  • 保持位置反馈,实时监控位置变化

4.1.2.3. 数据录制与存储

count = 1csv = open(CSV_path, "w")while input("INPUT: 输入 q 退出,直接回车录制: ") != "q":    current_pos = get_pos()    print(f"INFO: 第{count}个点位,记录位置: {current_pos}")    csv.write(",".join(map(str, current_pos)) + "\n")    count += 1csv.close()print("INFO: 录制结束,再次点击示教按钮退出示教模式")

数据完整性保证:每次录制后立即写入文件并刷新缓冲区,确保数据不会因为程序异常退出而丢失。

数据格式选择:选择CSV格式存储数据的原因包括:

  • 通用性强,几乎所有数据处理工具都支持CSV格式

  • 人类可读性强,便于调试和验证

  • 结构简单,解析效率高

  • 广泛支持,便于与其他工具集成

数据列属性:

  • 第1~6列:关节电机弧度

  • 第7列:夹爪张开距离,单位m

4.1.3. 点位录制程序的完整代码实现

#!/usr/bin/env python3# -*-coding:utf8-*-# 录制点位import os, timefrom piper_sdk import *
if __name__ == "__main__":    # 是否有夹爪    have_gripper = True    # 示教模式检测超时时间,单位:秒    timeout = 10.0    # 保存点位的CSV文件路径    CSV_path = os.path.join(os.path.dirname(__file__), "pos.csv")    # 初始化并连接机械臂    piper = Piper("can0")    interface = piper.init()    piper.connect()    time.sleep(0.1)
    def get_pos():        '''获取机械臂当前关节弧度和夹爪张开距离'''        joint_state = piper.get_joint_states()[0]        if have_gripper:            return joint_state + (piper.get_gripper_states()[0][0], )        return joint_state        print("INFO: 请点击示教按钮进入示教模式")    over_time = time.time() + timeout    while interface.GetArmStatus().arm_status.ctrl_mode != 2:        if over_time < time.time():            print("ERROR: 示教模式检测超时,请检查示教模式是否开启")            exit()        time.sleep(0.01)
    count = 1    csv = open(CSV_path, "w")    while input("INPUT: 输入 q 退出,直接回车录制: ") != "q":        current_pos = get_pos()        print(f"INFO: 第{count}个点位,记录位置: {current_pos}")        csv.write(",".join(map(str, current_pos)) + "\n")        count += 1    csv.close()    print("INFO: 录制结束,再次点击示教按钮退出示教模式")

4.2. 点位播放程序的实现

点位播放程序是系统的执行模块,负责读取录制的点位数据并控制机械臂重现这些位置。

4.2.1. 参数配置与数据加载

4.2.1.1. 播放参数配置

# 播放次数,0表示无限循环play_times = 1# 播放间隔,单位:秒,负数表示人工按键控制play_interval = 0# 运动速度百分比,建议范围:10-100move_spd_rate_ctrl = 100

参数设计分析:

play_times参数支持三种播放模式:

  • 单次播放(play_times = 1):适用于演示和测试

  • 多次播放(play_times > 1):适用于重复性任务

  • 无限循环(play_times = 0):适用于连续作业

play_interval的负值设计是一个巧妙的用户界面设计:

  • 正值:自动播放模式,系统按设定间隔自动执行

  • 零值:连续播放模式,点位间无延迟

  • 负值:手动控制模式,用户按键控制播放节奏

move_spd_rate_ctrl参数提供了速度控制功能,这对于不同应用场景非常重要:

  • 高速模式(80-100%):适用于空载快速移动

  • 中速模式(50-80%):适用于一般操作任务

  • 低速模式(10-50%):适用于精密操作和安全要求高的场合

4.2.1.2. 数据文件读取

try:    with open(CSV_path, 'r', encoding='utf-8') as f:        track = list(csv.reader(f))        if not track:            print("ERROR: 点位文件为空")            exit()        track = [[float(j) for j in i] for i in track]    # 转换为浮点数列表except FileNotFoundError:    print("ERROR: 点位文件不存在")    exit()

异常处理策略:

  • FileNotFoundError:处理文件不存在的情况

  • 空文件检查:防止读取空数据文件

  • 数据格式验证:确保数据能够正确转换为数值类型

数据类型转换:将字符串数据转换为浮点数的过程中,程序使用了列表推导式。

4.2.2. 安全停止函数

def stop():    '''停止机械臂;初次退出示教模式需先调用此函数才能使用CAN模式控制机械臂'''    interface.EmergencyStop(0x01)    time.sleep(1.0)    limit_angle = [0.1745, 0.7854, 0.2094]  # 2、3、5关节角度在限制范围内时才恢复机械臂,防止大角度直接掉落造成损坏    pos = get_pos()    while not (abs(pos[1]) < limit_angle[0] and abs(pos[2]) < limit_angle[0] and pos[4] < limit_angle[1] and pos[4] > limit_angle[2]):        time.sleep(0.01)        pos = get_pos()    # 恢复机械臂    piper.disable_arm()    time.sleep(1.0)

分阶段停止策略:停止函数采用了分阶段的安全停止策略

  1. 紧急停止阶段:EmergencyStop(0x01)发送紧急停止指令,立即停止所有关节运动(关节带阻抗)

  2. 安全位置等待:等待关键关节(2、3、5号关节)移动到安全范围内

  3. 系统恢复阶段:发送恢复指令,重新激活控制系统

安全范围设计:程序特别关注2、3、5号关节的位置,这是基于PIPER机械臂的机械结构特点

  • 2号关节(肩关节):控制大臂的俯仰运动,影响整体稳定性

  • 3号关节(肘关节):控制小臂角度,直接影响末端位置

  • 5号关节(腕关节):控制末端姿态,影响夹爪方向

安全角度范围的设定(10°、45°、12°)基于以下考虑:

  • 避免机械臂在重力作用下快速下落

  • 确保关节不会碰撞到机械限位

  • 为后续运动提供足够的操作空间

实时监控机制:程序采用实时轮询方式监控关节位置,确保只有在安全条件满足时才进行下一步操作。

4.2.3. 系统使能函数

def enable():    '''使能机械臂和夹爪'''    while not piper.enable_arm():        time.sleep(0.01)    if have_gripper:        time.sleep(0.01)        piper.enable_gripper()    interface.ModeCtrl(0x01, 0x01, move_spd_rate_ctrl, 0x00)    print("INFO: 使能成功")

机械臂使能:enable_arm()

夹爪使能:enable_gripper()

控制模式设置:ModeCtrl(0x01, 0x01, move_spd_rate_ctrl, 0x00)控制模式参数

  • 第一个参数(0x01):设置为CAN指令控制模式

  • 第二个参数(0x01):设置为关节运动模式

  • 第三个参数(0至100):设置运动速度百分比

  • 第四个参数(0x00):设置为位置速度模式

4.2.4. 播放控制逻辑

count = 0input("step 2: 回车开始播放点位")while play_times == 0 or abs(play_times) != count:    for n, pos in enumerate(track):        while True:            piper.move_j(pos[:-1], move_spd_rate_ctrl)            time.sleep(0.01)            current_pos = get_pos()            print(f"INFO: 第{count + 1}次播放,第{n + 1}个点位,当前位置: {current_pos},目标位置: {pos}")            if all(abs(current_pos[i] - pos[i]) < 0.0698 for i in range(6)):                break        if have_gripper and len(pos) == 7:            piper.move_gripper(pos[-1], 1)            time.sleep(0.5)        if play_interval < 0:            if n != len(track) - 1 and input("INPUT: 输入 q 退出,直接回车播放: ") == 'q':                exit()        else:            time.sleep(play_interval)    count += 1

关节控制:move_j()

  • 第一个参数:包含六个关节电机弧度的元组

  • 第二个参数:运动速度百分比,范围0~100

  • 夹爪控制:move_gripper()

  • 第一个参数:夹爪张开距离,单位m

  • 第二个参数:夹爪力矩,单位N/m

位置控制闭环系统:

  1. 目标设定:通过move_j()函数向各关节发送目标位置指令

  2. 状态反馈:通过get_pos()函数获取当前实际位置

  3. 误差计算:比较目标位置与实际位置的差值

  4. 收敛判断:当误差小于阈值时认为到达目标

多关节协调控制:all(abs(current_pos[i] - pos[i]) < 0.0698 for i in range(6))确保所有六个关节都达到目标位置后才进行下一步操作。

夹爪控制策略:夹爪控制采用独立的控制逻辑:

  • 只有在数据包含夹爪信息时才执行夹爪控制

  • 夹爪动作在关节运动完成后执行,避免干扰

  • 0.5秒的延时确保夹爪动作完全完成

播放节奏控制:程序支持三种播放节奏:

  • 自动连续播放:play_interval >= 0

  • 手动步进播放:play_interval < 0

  • 实时调整:用户可以随时中断播放

4.2.5. 点位播放程序的完整代码实现

#!/usr/bin/env python3# -*-coding:utf8-*-# 播放点位import os, time, csvfrom piper_sdk import Piper
if __name__ == "__main__":    # 是否有夹爪    have_gripper = True    # 播放次数,0表示无限循环    play_times = 1    # 播放间隔,单位:秒,负数表示人工按键控制    play_interval = 0    # 运动速度百分比,建议范围:10-100    move_spd_rate_ctrl = 100    # 切换CAN模式超时时间,单位:秒    timeout = 5.0    # 保存点位的CSV文件路径    CSV_path = os.path.join(os.path.dirname(__file__), "pos.csv")    # 读取点位文件    try:        with open(CSV_path, 'r', encoding='utf-8') as f:            track = list(csv.reader(f))            if not track:                print("ERROR: 点位文件为空")                exit()            track = [[float(j) for j in i] for i in track]    # 转换为浮点数列表    except FileNotFoundError:        print("ERROR: 点位文件不存在")        exit()
    # 初始化并连接机械臂    piper = Piper("can0")    interface = piper.init()    piper.connect()    time.sleep(0.1)
    def get_pos():        '''获取机械臂当前关节弧度和夹爪张开距离'''        joint_state = piper.get_joint_states()[0]        if have_gripper:            return joint_state + (piper.get_gripper_states()[0][0], )        return joint_state    
    def stop():        '''停止机械臂;初次退出示教模式需先调用此函数才能使用CAN模式控制机械臂'''        interface.EmergencyStop(0x01)        time.sleep(1.0)        limit_angle = [0.1745, 0.7854, 0.2094]  # 2、3、5关节弧度在限制范围内时才恢复机械臂,防止大弧度直接掉落造成损坏        pos = get_pos()        while not (abs(pos[1]) < limit_angle[0] and abs(pos[2]) < limit_angle[0] and pos[4] < limit_angle[1] and pos[4] > limit_angle[2]):            time.sleep(0.01)            pos = get_pos()        # 恢复机械臂        piper.disable_arm()        time.sleep(1.0)        def enable():        '''使能机械臂和夹爪'''        while not piper.enable_arm():            time.sleep(0.01)        if have_gripper:            time.sleep(0.01)            piper.enable_gripper()        interface.ModeCtrl(0x01, 0x01, move_spd_rate_ctrl, 0x00)        print("INFO: 使能成功")
    print("step 1: 播放前请确保机械臂已退出示教模式")    if interface.GetArmStatus().arm_status.ctrl_mode != 1:        stop()  # 初次退出示教模式需先调用此函数才能切换至CAN模式    over_time = time.time() + timeout    while interface.GetArmStatus().arm_status.ctrl_mode != 1:        if over_time < time.time():            print("ERROR: CAN模式切换失败,请检查是否退出示教模式")            exit()        interface.ModeCtrl(0x01, 0x01, move_spd_rate_ctrl, 0x00)        time.sleep(0.01)        enable()    count = 0    input("step 2: 回车开始播放点位")    while play_times == 0 or abs(play_times) != count:        for n, pos in enumerate(track):            while True:                piper.move_j(pos[:-1], move_spd_rate_ctrl)                time.sleep(0.01)                current_pos = get_pos()                print(f"INFO: 第{count + 1}次播放,第{n + 1}个点位,当前位置: {current_pos},目标位置: {pos}")                if all(abs(current_pos[i] - pos[i]) < 0.0698 for i in range(6)):                    break            if have_gripper and len(pos) == 7:                piper.move_gripper(pos[-1], 1)                time.sleep(0.5)            if play_interval < 0:                if n != len(track) - 1 and input("INPUT: 输入 q 退出,直接回车播放:") == 'q':                    exit()            else:                time.sleep(play_interval)        count += 1

五、小结

以上基于松灵PIPER机械臂实现了固定点位录制与播放功能。通过对Python SDK的应用,可以实现机械臂特定位置的记录和重复执行,为教学演示和自动化操作提供了强有力的技术支撑.有任何相关使用的疑问都可以联系我们:support@agilex.ai

加载中...