目录
复合机器人硬件完成搭建之后进行软件的适配,机器人各模块之间采用TCP/IP的通信方式。主要实现方式为机械臂和底盘均为Socket通信的服务端,NX主控作为客户端,创建连接且分别连接机械臂与移动底盘,连接成功之后机械臂、移动底盘的控制指令与返回值接收都在NX主控完成。
底盘API接口资料
我们先来看一下移动底盘控制相关的资料:
移动底盘提供一套软件API手册,其中包含机器人地图查询、状态查询、点位创建等等接口,如下所示:
单目标点移动示例如下,实现方法为通过Socket发送示例字符即可。
获取机器人全局状态指令如下:
发送示例及返回值:
其他指令可以通过云盘下载查看,下面我们用Python做程序与移动底盘进行通信,实现控制底盘。
机械臂JSON协议资料
机械臂的控制可以直接发送JSON协议指令和使用API进行通信,在此项目中均可使用。
机械臂资料中JSON指令资料(参考文档已存储至云盘中)
(1)查询机械臂状态
功能描述 | 查询机械臂状态 |
参数说明 | get_current_arm_state:查询机械臂状态 |
命令格式 | {s:s} |
示例 | {"command":"get_current_arm_state"} |
说明:查询机械臂状态 | |
返回值 | {"state":"current_arm_state","arm_state":{"joint":[100,200,300,400,500,600],"pose":[100000,200000,30000,400,500,600],"arm_err":0,"sys_err":0}} |
说明:反馈机械臂状态, 关节1~6角度依次为:0.1°,0.2°,0.3°。0.4°,0.5°,0.6°,精度:0.001° 位置:x:0.1m,y:0.2m,z:0.03m,位置精度:0.001mm 姿态:rx:0.4rad,ry:0.5rad,rz:0.6rsd,姿态精度:0.001rad 机械臂错误代码,指机械臂运行规划中的软件错误:0 控制器错误代码,指控制器运行过程中的硬件错误:0 |
(2)MoveJ:关节运动
功能描述 | MoveJ:关节运动 |
参数说明 | movej:关节运动 joint:目标关节角度,精度0.001° v:速度百分比例系数,0~100 r:交融半径,精度0.001m,暂不支持交融,默认0 |
命令格式 | {s:s,s:[i,i,i,i,i,i],s:i,s:i} |
示例 | {"command":"movej","joint":[10100,200,20300,30400,500,20600],"v":50,"r":0} |
说明:关节运动,关节角度[10.1°,0.2°,20.3°,30.4°,0.5°,20.6°],速度系数50%,交融半径:0 | |
返回值 | 格式:{s:s,s:b,s:i},true-到达目标位置,false-规划失败;0:机械臂运动轨迹到位 |
{"state":"current_trajectory_state","trajectory_state":true,"device":0} |
(3)MoveL:直线运动
功能描述 | MoveL:直线运动 |
参数说明 | movel:直线运动 pose:目标位姿,位置精度:0.001mm,姿态精度:0.001rad v:速度百分比例系数,0~100 r:交融半径,精度0.001m,暂不支持交融,默认0 |
命令格式 | {s:s,s:[i,i,i,i,i,i],s:i,s:i} |
示例 | {"command":"movel","pose":[100000,200000,30000,400,500,600],"v":50,"r":0} |
说明:直线运动, 目标位置:x:0.1m,y:0.2m,z:0.03m 目标姿态:rx:0.4rad,ry:0.5rad,rz:0.6rad 速度系数50%, 不交融 | |
返回值 | 格式:{s:s,s:b,s:i},true-到达目标位置,false-规划失败;0:机械臂运动轨迹到位 |
{"state":"current_trajectory_state","trajectory_state":true,"device":0} | |
备注: | MOVL指令也适用于目标位置不变,姿态变化 |
Python实现Socket通信
首先来看一下如何用Python实现Socket通信:
Python 提供了两个级别访问的网络服务。:
- 低级别的网络服务支持基本的 Socket,它提供了标准的 BSD Sockets API,可以访问底层操作系统Socket接口的全部方法。
- 高级别的网络服务模块 SocketServer, 它提供了服务器中心类,可以简化网络服务器的开发。
本文中仅对Socket进行讲述。注意:在使用Socket创建连接时,使用完毕之后必须调用close()方法关闭连接。
Scoket()函数介绍
Socket又称"套接字",应用程序通常通过"套接字"向网络发出请求或者应答网络请求,使主机间或者一台计算机上的进程间可以通讯。
Python3 中,我们用 socket() 函数来创建套接字,语法格式如下:
socket.socket([family[, type[, proto]]])
创建客户端
Socket客户端创建完成,并且连接服务端之后,会接收到服务端向外广播的信息,且服务端可以获得客户端的IP及其他信息。创建客户端程序如下所示:
# 导入 socket、sys 模块
import socket
import sys
# 创建 socket 对象
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 服务端/移动底盘的IP
host = '192.168.10.10'
# 移动底盘的端口号
port = 8001
# 连接服务,指定主机和端口
s.connect((host, port))
# 接收小于 1024 字节的数据
msg = s.recv(1024)
s.close()
print (msg.decode('utf-8'))
实现底盘通信
import socket
import json
import time
client1 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
#底盘的IP
host1 = '192.168.10.10'
#底盘的控制端口
port1 = 31001
#创建与移动底盘的连接
client1.connect((host1, port1))
str1 = ""
#查询底盘的地图列表指令
point1 = '/api/map/list'
#发送指令
client1.send(point1.encode('utf-8'))
#接收底盘返回
data1 = client1.recv(1024).decode()
print(data1)
point2= '/api/move?marker=071901'
client1.send(point2.encode('utf-8'))
data1 = client1.recv(1024).decode()
point3='/api/move?marker=071902'
client1.send(point3.encode('utf-8'))
data1 = client1.recv(1024).decode()
client1.close()
实现机械臂通信的Python程序
import socket
import time
import json
#创建协议指令,下方几个为机械臂运动指令。
point1= '{"command":"movej","joint":[-41395,195,-2699,103268,872,74955,12639],"v":50,"r":0}\r\n'
point2= '{"command":"movej","joint":[-42635,5399,9327,108735,-766,64883,21533],"v":30,"r":0}\r\n'
point3= '{"command":"movel","pose":[181030,-121700,225700,3132,16,2189],"v":10,"r":0}\r\n'
point4= '{"command":"movel","pose":[181030,-121700,265770,3132,16,2189],"v":10,"r":0}\r\n'
point5= '{"command":"movej","joint":[-42845,32180,-41576,52599,21931,100707,20650],"v":30,"r":0}\r\n'
point6= '{"command":"movel","pose":[154270,-293080,299560,3133,16,2189],"v":10,"r":0}\r\n'
point7= '{"command":"movel","pose":[154270,-293080,354680,3133,16,2189],"v":10,"r":0}\r\n'
#创建Socket连接
client1 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
host1 = '192.168.1.18'
port1 = 8080
client1.connect((host1, port1))
client1.send(point1.encode('utf-8'))
data1 = client1.recv(1024).decode()
time.sleep(5)
print(data1)
client1.send(point2.encode('utf-8'))
data1 = client1.recv(1024).decode()
time.sleep(0.5)
client1.send(point3.encode('utf-8'))
data1 = client1.recv(1024).decode()
time.sleep(0.5)
speed_close = '{"command":"write_single_register","port":1,"address":264,"data":1,"device":1}\r\n'
speed_100 = '{"command":"write_single_register","port":1,"address":262,"data":100,"device":1}\r\n'
client1.send(speed_100.encode('utf-8'))
data3 = client1.recv(1024).decode()
time.sleep(0.5)
str_1000= '{"command":"write_single_register","port":1,"address":261,"data":1000,"device":1}\r\n'
client1.send(str_1000.encode('utf-8'))
data6 = client1.recv(1024).decode()
time.sleep(0.5)
client1.send(speed_close.encode('utf-8'))
data2 = client1.recv(1024).decode()
time.sleep(0.5)
client1.send(point4.encode('utf-8'))
data1 = client1.recv(1024).decode()
time.sleep(0.5)
client1.send(point5.encode('utf-8'))
data1 = client1.recv(1024).decode()
time.sleep(0.5)
client1.send(point6.encode('utf-8'))
data1 = client1.recv(1024).decode()
time.sleep(0.5)
str_0= '{"command":"write_single_register","port":1,"address":261,"data":0,"device":1}\r\n'
client1.send(str_0.encode('utf-8'))
data4 = client1.recv(1024).decode()
time.sleep(0.5)
client1.send(speed_close.encode('utf-8'))
data2 = client1.recv(1024).decode()
time.sleep(0.5)
client1.send(point7.encode('utf-8'))
data1 = client1.recv(1024).decode()
time.sleep(0.5)
client1.close()
复合机器人整体程序只需将底盘与机械臂的控制程序整合到一处即可,此处暂不做解释。
由于机械臂相关软件版本不定期更新,如果你使用的软件接口或协议与本文有出入,请联系官方技术人员及时更新。