跳到主要内容

Python快速集成

1. Python 快速集成

因为我们的库是使用 C++开发的,所以不能直接通过 interface.h 中的函数调用,而需要使用到 Python 中的 ctypes 标准库模块,使用这个模块可以帮助我们调用动态链接库(DLL)或共享库(shared library)中的函数,而无需编写扩展模块。

我们可以将 interface.h 中的方法封装到 RobotController 这个对象中,例如

import ctypes

class RobotController:
def __init__(self, library_path):
# 加载动态链接库
self.lib = ctypes.CDLL(library_path)
def connect_robot(self, ip, port, robot_name):
# 定义函数参数和返回类型
self.lib.connect_robot.argtypes = [ctypes.c_char_p, ctypes.c_char_p, ctypes.c_char_p]
self.lib.connect_robot.restype = ctypes.c_int

# 准备函数参数
ip_arg = ctypes.c_char_p(ip.encode())
port_arg = ctypes.c_char_p(port.encode())
robot_name_arg = ctypes.c_char_p(robot_name.encode())

# 调用函数
result = self.lib.connect_robot(ip_arg, port_arg, robot_name_arg)

# 检查函数调用结果
if result != 0:
print("Error occurred during robot connection.")
else:
print("Robot connected successfully.")

def robot_movej(self, pos, vel, coord, acc, dec, robot_name):
# 告诉 Python 解释器关于 robot_movej 函数的参数类型和返回类型的信息。
self.lib.robot_movej.argtypes = [ctypes.POINTER(ctypes.c_double), ctypes.c_int, ctypes.c_int, ctypes.c_int, ctypes.c_int, ctypes.c_char_p]
self.lib.robot_movej.restype = ctypes.c_int

# 准备函数参数
pos_array = (ctypes.c_double * len(pos))(*pos)
vel_arg = ctypes.c_int(vel)
coord_arg = ctypes.c_int(coord)
acc_arg = ctypes.c_int(acc)
dec_arg = ctypes.c_int(dec)
robot_name_arg = ctypes.c_char_p(robot_name.encode())

# 调用函数
result = self.lib.robot_movej(pos_array, vel_arg, coord_arg, acc_arg, dec_arg, robot_name_arg)

# 检查函数调用结果
if result != 0:
print("Error occurred during robot movement.")
else:
print("Robot movement successful.")

# 使用示例
library_path = "libnrc_host.so"
robot_controller = RobotController(library_path)

ip = "192.168.1.13"
port = "6001"
robot_name = "your_robot_name"
robot_controller.connect_robot(ip, port, robot_name)

pos = [1.0, 2.0, 3.0, 4.0, 5.0, 6.0]
vel = 10
coord = 0
acc = 100
dec = 100
robot_controller.move_robot(pos, vel, coord, acc, dec, robot_name)

可以看到使用 ctypes 模块添加 C 函数非常简单,在此不再多叙述,我们最后举一个添加获取当前点位的函数的示例

def get_current_position(self, coord, robot_name):
# 定义函数参数和返回类型
self.lib.get_current_position.argtypes = [ctypes.POINTER(ctypes.c_double), ctypes.c_int, ctypes.c_char_p]
self.lib.get_current_position.restype = ctypes.c_int

# 准备函数参数
pos = (ctypes.c_double * 7)() # 创建一个长度为7的双精度浮点数数组
coord_arg = ctypes.c_int(coord)
robot_name_arg = ctypes.c_char_p(robot_name.encode())

# 调用函数
result = self.lib.get_current_position(pos, coord_arg, robot_name_arg)

# 检查函数调用结果
if result != 0:
print("Error occurred while getting current position.")
return None
else:
print("Current position retrieved successfully.")
return list(pos)

# 使用示例
coord = 0
current_position = robot_controller.get_current_position(coord, robot_name)
print("Current position:", current_position)

其余方法你可以根据 interface.h 文件以及自己的需求自行添加

如果我们的 interface.h 中有一个方法是接收一个 struct,在 python 中又该如何声明呢?

假设有一个 C 函数声明如下:

struct MoveCmd {
double pos[7];
int coord;
double velocity;
double acc;
double dec;
int pl;
int toolNum;
int userNum;
};

int queue_motion_push_back_moveJ(MoveCmd cmd,const char* robotName);

然后你可以在 Python 中调用这个函数,示例代码如下:


# 定义与结构体对应的 Python 类
# 定义 MoveCmd 结构体
class MoveCmd(ctypes.Structure):
_fields_ = [("pos", ctypes.c_double * 7),
("coord", ctypes.c_int),
("velocity", ctypes.c_double),
("acc", ctypes.c_double),
("dec", ctypes.c_double),
("pl", ctypes.c_int),
("toolNum", ctypes.c_int),
("userNum", ctypes.c_int)]

def queue_motion_push_back_moveJ(self, cmd, robot_name):
# 定义函数参数和返回类型
self.lib.queue_motion_push_back_moveJ.argtypes = [MoveCmd, ctypes.c_char_p]
self.lib.queue_motion_push_back_moveJ.restype = ctypes.c_int

# 准备函数参数
cmd_struct = cmd
robot_name_arg = ctypes.c_char_p(robot_name.encode())

# 调用函数
result = self.lib.queue_motion_push_back_moveJ(cmd_struct, robot_name_arg)

# 检查函数调用结果
if result != 0:
print("Error occurred while pushing back moveJ motion command to queue.")
else:
print("MoveJ motion command pushed back to queue successfully.")

# 使用示例
move_cmd = MoveCmd()
move_cmd.pos = (ctypes.c_double * 7)(* [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0])
move_cmd.coord = 0
move_cmd.velocity = 10.0
move_cmd.acc = 100.0
move_cmd.dec = 100.0
move_cmd.pl = 1
move_cmd.toolNum = 0
move_cmd.userNum = 0

robot_name = "your_robot_name"
robot_controller.queue_motion_push_back_moveJ(move_cmd, robot_name)