Skip to content

Latest commit

 

History

History
279 lines (214 loc) · 11 KB

File metadata and controls

279 lines (214 loc) · 11 KB

Onero Gripper Python 包

预编译 Python 扩展模块(pybind11)。整个 SDK 只控制夹爪,独立交付、开箱即用。

模块名import onerogripper(pybind11 原生扩展,包名 onerogripper)。


目录


一、目录结构

python/
├── conda_channel/                            # 离线 conda 渠道
│   ├── linux/{linux-64, linux-aarch64}/
│   └── windows/win-64/
└── wheels/
    └── linux-riscv64/onerogripper-*.whl       # RISC-V wheel

类型存根 onerogripper.pyi 随包自带,安装后位于 <env>/lib/python3.12/site-packages/onerogripper.pyi;预编译扩展位于同目录的 onerogripper.cpython-312-*.so(Linux)或 onerogripper.cp312-*.pyd(Windows)。


二、安装

conda create -n onerogripper python=3.12 -y
conda activate onerogripper

# Linux
conda install -c conda-forge -c ./python/conda_channel/linux onerogripper -y

# Windows (PowerShell / cmd)
conda install -c conda-forge -c ./python/conda_channel/windows onerogripper -y

⚠️ 不要用反斜杠 .\python\conda_channel\windows。conda 只把开头为 ./ ../ / ~ 或盘符 C:\ 的字符串识别为本地路径;.\ 不在此列,会被当成渠道名拼到 https://conda.anaconda.org/ 后面去联网(Windows 必现)。正斜杠在 Windows 上同样有效。

若仍想彻底避免歧义,可改用绝对路径或 file:// URL(在仓库根目录执行):

conda install -c conda-forge -c "file://$PWD/python/conda_channel/linux" onerogripper -y   # Linux
conda install -c conda-forge -c "file:///$($PWD.Path -replace '\\','/')/python/conda_channel/windows" onerogripper -y   # Windows PowerShell

也可用 micromamba install ... 替代 conda install

安装时必须保留 -c conda-forge,本地 channel 仅提供 onerogripper 自身,依赖从 conda-forge 拉取。

2.1 安装自检

python -c "import onerogripper; print('OK,', onerogripper.__file__)"

无硬件连接时 OneroGripper("/dev/ttyACM0") 不会抛异常,但 valid() 返回 False—— 这是预期行为,可用于纯环境自检。

2.2 RISC-V (linux-riscv64):用 wheel 安装

RISC-V 随包提供 linux-riscv64 wheel,不走 conda channel:

# 1. 进入用户仓根目录

# 2. 使用 Python 3.12;wheel 标签是 cp312
python3.12 -m venv .venv_onerogripper
. .venv_onerogripper/bin/activate
python -m pip install --upgrade pip

# 3. 安装随包 wheel
python -m pip install --no-deps ./python/wheels/linux-riscv64/onerogripper-*.whl

# 4. 自检
python -c "import onerogripper; print('OK,', onerogripper.__file__)"

onerogripper 的 RISC-V wheel 文件名通常类似 onerogripper-<version>-cp312-abi3-linux_riscv64.whl。其中 cp312 表示 Python 3.12, abi3 是预期的稳定 ABI 标签,linux_riscv64 是平台标签;请不要手动改名。

夹爪 Python wheel 不打包第三方机器人 / 数学库;运行时只需要目标系统的标准 C/C++ 运行时库。若 import onerogripper 报动态库加载错误,先确认当前机器是 riscv64、 Python 是 3.12,且 wheel 来自 python/wheels/linux-riscv64/


三、数据类

import onerogripper

s = onerogripper.GripperStatus()    # position / velocity / force / error / valid
字段 类型 单位 / 含义
position float 开合位置,百分比 0..100
velocity float 速度,百分比/s
force float 力,N,限幅 ±40
error int 故障码,0 = 正常
valid bool 该帧状态是否有效

夹爪触觉数据类(get_tactile() 返回):

ts = onerogripper.GripperTactileStatus()         # sensors / valid
sv = onerogripper.GripperTactileSensorStatus()   # sensor_id / total_force / points / valid
pt = onerogripper.GripperTactileValue()          # point_id / fx / fy / fz / valid
字段 类型 含义
GripperTactileStatus sensors list[GripperTactileSensorStatus] 2 个触觉传感器
valid bool 是否读到有效数据
GripperTactileSensorStatus sensor_id int 传感器编号
total_force GripperTactileValue 该传感器合力
points list[GripperTactileValue] 各测点读数
valid bool 该传感器是否有效
GripperTactileValue point_id int 0 = 合力,其余为各测点
fx / fy / fz float 三轴受力,N
valid bool 该读数是否有效

返回码(int

 0   # SUCCESS           成功
-1   # INVALID_PARAMS    会话未就绪 / 参数非法(如 max_* <= 0)
-4   # EXECUTION_FAILED  串口/总线写失败或状态刷新失败
-6   # INTERRUPTED       move_position 被 request_stop() 取消

四、OneroGripper 详解

class OneroGripper:
    def __init__(self, device: str) -> None: ...      # 波特率固定 921600
    def valid(self) -> bool: ...
    def enable(self) -> int: ...
    def disable(self) -> int: ...
    def status(self) -> GripperStatus: ...
    def get_tactile(self) -> GripperTactileStatus: ...
    def set_position(self, percent: float) -> int: ...
    def move_position(self, percent: float, max_vel: float = 100.0,
                      max_acc: float = 250.0, max_jerk: float = 1000.0) -> int: ...
    def force_control(self, torque: float) -> int: ...
    def request_stop(self) -> None: ...
    def clear_stop(self) -> None: ...

构造时打开独立串口会话;构造不抛异常,需用 valid() 判断会话是否就绪。

方法 参数 返回 语义
OneroGripper(device) device:Linux "/dev/ttyACM0" / Windows "COM3" 打开独立串口会话
valid() bool 会话是否就绪(串口已打开且夹爪已注册)
enable() / disable() int 使能 / 失能夹爪电机;运动前先 enable()
set_position(percent) 0..100 int 单帧位置保持(非阻塞)
move_position(percent, max_vel=100.0, max_acc=250.0, max_jerk=1000.0) percent0..100max_* 速度/加速度/加加速度上限(须 >0 int 100 Hz 点到点 S 曲线规划,阻塞直到到位
force_control(torque) torque:N int 单帧力保持,内部钳位 ±40 N
status() GripperStatus 刷新并返回夹爪状态
get_tactile() GripperTactileStatus 刷新并返回 2 个触觉传感器的合力与各测点读数
request_stop() / clear_stop() None 置位 / 复位中断标志:request_stop() 使正在进行的 move_position() 尽快返回 INTERRUPTED(-6);新一轮运动前 clear_stop() 复位

enable / disable / status / get_tactile / set_position / move_position / force_control 在执行期间释放 GIL, 因此阻塞的 move_position() 进行中,可从另一个线程调用 request_stop() 将其取消。

get_tactile() 会触发一次读取;读数前先判 tactile.valid / sensor.valid / point.valid, 通常需先 enable() 并施加一定夹持力才会读到非零数据。


五、完整示例

import onerogripper as g

grip = g.OneroGripper("/dev/ttyACM0")        # Windows: "COM3"
assert grip.valid(), "failed to open gripper"

grip.enable()

grip.move_position(80.0)                      # 闭合到 80%(默认速度/加速度上限)

s = grip.status()
print(f"pos={s.position:.1f}% vel={s.velocity:.1f} force={s.force:.2f}N")

grip.force_control(20.0)                       # 20 N 力保持(±40 N 上限)

grip.disable()

线程取消正在进行的运动:

import threading, onerogripper as g

grip = g.OneroGripper("/dev/ttyACM0")
grip.enable()

# 后台线程跑一段长行程
t = threading.Thread(target=lambda: grip.move_position(100.0, 10.0, 20.0, 50.0))
t.start()

# 主线程需要时取消
grip.request_stop()      # move_position 将返回 -6 INTERRUPTED
t.join()
grip.clear_stop()        # 复位后才能再次运动

读取触觉传感器:

import onerogripper as g

grip = g.OneroGripper("/dev/ttyACM0")
assert grip.valid(), "failed to open gripper"

grip.enable()
grip.move_position(100.0)        # 闭合到位
grip.force_control(10.0)         # 施加一点夹持力以产生触觉读数

tac = grip.get_tactile()
if tac.valid:
    for sensor in tac.sensors:
        if not sensor.valid:
            continue
        tf = sensor.total_force          # 合力
        print(f"sensor {sensor.sensor_id} total "
              f"x={tf.fx:.2f} y={tf.fy:.2f} z={tf.fz:.2f} N")
        for p in sensor.points:          # 各测点
            if p.valid:
                print(f"  point {p.point_id} "
                      f"x={p.fx:.2f} y={p.fy:.2f} z={p.fz:.2f} N")

grip.disable()

六、错误诊断

现象 原因 / 处理
PackagesNotFoundError: onerogripper -c channel 路径不对;python/conda_channel/linux/ 下应有 linux-64/(或 linux-aarch64/)子目录及 repodata.json
UnsatisfiableError 用全新环境:conda create -n onerogripper python=3.12 -y;安装命令保留 -c conda-forge
not a supported wheel on this platform 当前 Python / 架构与 wheel 标签不匹配;RISC-V wheel 需要 riscv64 机器和 Python 3.12
python/wheels/linux-riscv64/onerogripper-*.whl 找不到 用户仓尚未同步 RISC-V wheel;确认存在 python/wheels/linux-riscv64/onerogripper-*.whl
import onerogripperImportError / DLL load failed(Windows) 确认已 conda activate onerogripper,IDE 解释器是该环境的 Python
OneroGripper(...).valid() 返回 False 串口路径 / 权限:Linux ls /dev/ttyACM*,必要时 sudo chmod 666 /dev/ttyACM0 或加入 dialout 组;Windows 在设备管理器查 COM 号
同一设备第二次打开 valid() 仍为 False 串口被独占:确认没有其他进程正占用该设备
方法返回 -1 会话未就绪(valid()==False);或 move_positionmax_vel/acc/jerk <= 0
方法返回 -4 串口 / 总线写失败或状态刷新失败:检查连线、供电、设备是否被拔出
move_position 返回 -6 运动期间被 request_stop() 取消;下次运动前调用 clear_stop() 复位
get_tactile().validFalse 或读数全 0 会话未就绪(valid()==False),或夹爪未 enable() / 未接触受力;先 enable() 并施加夹持力再读