Skip to main content

Python quick integration

1. Python quick integration

Since our library is developed in C++, it cannot be called directly through functions in interface.h. Instead, we can utilize the ctypes standard library module in Python to call functions from dynamic link libraries (DLL) or shared libraries without the need to write extension modules.

We can encapsulate the methods from interface.h into the RobotController object as shown below.

import ctypes

class RobotController:
def __init__(self, library_path):
# Load the dynamic link library
self.lib = ctypes.CDLL(library_path)
def connect_robot(self, ip, port, robot_name):
# Define function argument types and return type
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

# Prepare function arguments
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())

# Call the function
result = self.lib.connect_robot(ip_arg, port_arg, robot_name_arg)

# Check the function call result
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):
# Provide the Python interpreter with information about the argument types and return type of the robot_movej function.
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

# Prepare function arguments
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())

# Call the function
result = self.lib.robot_movej(pos_array, vel_arg, coord_arg, acc_arg, dec_arg, robot_name_arg)

# Check the function call result
if result != 0:
print("Error occurred during robot movement.")
else:
print("Robot movement successful.")

# Usage example
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)

It's great to see that using the ctypes module to add C functions is very simple, so I won't elaborate further here. Let's just give an example of adding a function to get the current position.

def get_current_position(self, coord, robot_name):
# Define function argument types and return type
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

# Prepare function arguments
pos = (ctypes.c_double * 7)() # Create an array of double-precision floating-point numbers with a length of 7
coord_arg = ctypes.c_int(coord)
robot_name_arg = ctypes.c_char_p(robot_name.encode())

# Call the function
result = self.lib.get_current_position(pos, coord_arg, robot_name_arg)

# Check the function call result
if result != 0:
print("Error occurred while getting current position.")
return None
else:
print("Current position retrieved successfully.")
return list(pos)

# Usage example
coord = 0
current_position = robot_controller.get_current_position(coord, robot_name)
print("Current position:", current_position)

You can add other methods according to the interface.h file and your own needs

If we have a method in interface.h that receives a struct, how would you declare it in Python?

Suppose there is a C function declared as follows:

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);

Then you can call this function in Python, with sample code like this:


# Define the Python class corresponding to the struct
# Define the MoveCmd struct
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):
# Define function argument types and return type
self.lib.queue_motion_push_back_moveJ.argtypes = [MoveCmd, ctypes.c_char_p]
self.lib.queue_motion_push_back_moveJ.restype = ctypes.c_int

# Prepare function arguments
cmd_struct = cmd
robot_name_arg = ctypes.c_char_p(robot_name.encode())

# Call the function
result = self.lib.queue_motion_push_back_moveJ(cmd_struct, robot_name_arg)

# Check the function call result
if result != 0:
print("Error occurred while pushing back moveJ motion command to queue.")
else:
print("MoveJ motion command pushed back to queue successfully.")

# Usage example
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)