ARCS 脚本编程快速入门
1. ARCS脚本简介
ARCS的脚本编程是指⽤脚本语⾔来控制机器⼈。这种编程方式基于LUA语言,它遵循LUA语法规则,为用户提供了灵活而强大的编程环境。
2. LUA语法
LUA语法教程可参考 https://www.runoob.com/lua/lua-tutorial.html
2.1 常用变量类型
类型 | 说明 | 示例 |
---|---|---|
nil | 表示一个无效值。 当打印一个没有被赋值的变量时,便会输出一个nil值。 |
nil |
boolean | 布尔值,只有两个可选值:true和false。 | true false |
number | 数字,包括整型、浮点型。 | 1 -5 3.1415 |
string | 字符串。一对双引号或单引号之间的字符。 | "abc" 'abc' |
function | 自定义函数。 | |
table | 表。用{}表示。默认索引从1开始。 | {1, 2, 3} |
2.2 函数
2.2.1 函数定义
语法定义:
function MyFunc(param)
-- Do something
end
示例:
自定义加函数
function add(a,b) return a+b end
函数调用
sum = add(3,4)
2.2.2 多返回值
LUA函数可以无返回值,也可以有一个或多个返回值。
示例:
自定义多返回值
function add(a,b) return a,b,(a+b) end
函数调用
x,y,z = add(a,b)
2.3 条件语句
2.3.1 if 语句
语法格式:
if(布尔表达式)
then
--[ 在布尔表达式为 true 时执行的语句 --]
end
2.3.2 if..else 语句
语法格式:
if(布尔表达式)
then
--[ 布尔表达式为 true 时执行该语句块 --]
else
--[ 布尔表达式为 false 时执行该语句块 --]
end
2.4 循环语句
2.4.1 while 循环
语法格式:
while(condition)
do
statements
end
2.4.2 for 循环
数值for循环
语法格式:
for var=exp1,exp2,exp3 do <执行体> end
泛型for循环
语法格式:
--打印数组a的所有值 number = {"one", "two", "three"} for i, num in ipairs(number) do print(i, num) end
i是数组索引值,num是对应索引的数组元素值。
ipairs是Lua提供的一个迭代器函数,用来迭代数组。
2.4.3 repeat...until
语法格式:
repeat
statements
until( condition )
3.ARCS脚本的API查看方法
可以通过SDK API手册查找LUA脚本的API定义。
步骤如下:
打开SDK API 手册链接:ARCS SDK API: 首页 (aubo-robotics.cn)
点击“文件”,可以查看到所有SDK头文件的列表
API分类模块化,一个.h头文件对应一个模块。模块分类如下:
模块名称 头文件名 说明 力控模块 force_control.h 力控接口 IO控制模块 io_control.h IO控制接口 运动控制模块 motion_control.h 运动控制接口 机器人算法模块 robot_algorithm.h 机器人算法相关的对外接口 机器人配置模块 robot_config.h 获取机器人配置接口,如获取DH参数、碰撞等级、安装位姿等等 机器人管理模块 robot_manage.h 机器人管理接口,如上电、启动、拖动示教模式等 机器人状态模块 robot_state.h 获取机器人状态接口,如关节速度、关节角度、固件/硬件版本 数学模块 math.h 数学方法接口,如欧拉角与四元数转换、位姿的加减运算 寄存器模块 register_control.h 寄存器操作接口,用于三个模块之间的数据交换功能 运行时模块 runtime_machine.h 脚本解释器运行时接口, 可以实现脚本解释器的暂停、脚本解释器的设置/取消断点 串口通信模块 serial.h 串口通信接口 socket通信模块 socket.h Socket通信接口 同步运行模块 sync_move.h 同步运行接口 系统信息模块 system_info.h 获取系统信息接口,如接口板的版本号、示教器软件的版本号 日志系统模块 trace.h 向控制器日志系统注入日志方面的接口
4. 根据模块查找需要的API定义。例如,想查找关节运动的API定义,关节运动属于运动模块,运动模块对应motion_control.h。所以,点击“motion_control.h”。
5. 点击“arcs::common_interface::MotionControl”,可查看其成员函数。
成员函数如下图所示:
7. 找到关节运动对应的函数名——moveJoint,点击“moveJoint”
8. moveJoint函数的定义如下图所示,其中,Lua函数原型就是moveJoint的LUA语法定义。
9. 根据上面moveJoint的LUA函数定义,moveJoint示例如下:
pi = 3.14159265358979323846
-- 关节角,单位:弧度
q = {-0.93/180*pi, -15.77/180*pi, 97.57/180*pi, 23.33/180*pi, 89.99/180*pi, -1.82/180*pi}
moveJoint(Waypoint_1_q, 1, 1, 0, 0)
机械臂以1rad/s的速度和1rad/s^2的加速度做关节运动到路点[-0.93°, -15.77°, 97.57°, 23.33°, 89.99°, -1.82°]。
4. 在示教器中使用脚本的方法
以下是在示教器中新建、编写和运行脚本的操作步骤:
在“编程”界面中,点击“新建”。新建一个工程。
在“模板”程序节点中,选择“脚本”。
脚本代码分为“行脚本”和“脚本文件”这两种类型。下面示例讲解的是脚本文件。
选择“文件”,点击“保存为”。
输入脚本文件名,点击“保存”。
点击“编辑”
将下面代码添加进去。
pi = 3.14159265358979323846 -- 关节⾓,单位:弧度 Waypoint_1_q = {-0.93/180*pi, -15.77/180*pi, 97.57/180*pi, 23.33/180*pi, 89.99/180*pi, -1.82/180*pi} Waypoint_2_q = {-16.67/180*pi, -21.25/180*pi, 56.19/180*pi, -12.57/180*pi, 89.99/180*pi, -17.56/180*pi} Waypoint_3_q = {30.22/180*pi, -14.97/180*pi, 61.42/180*pi, -13.62/180*pi, 89.99/180*pi, 29.33/180*pi} -- 设置运动速度⽐率 setSpeedFraction(0.8) -- 以关节运动的⽅式依次经过3个路点:Waypoint_1、Waypoint_2和Waypoint_3 moveJoint(Waypoint_1_q, 1, 1, 0, 0) -- 将信息打印到aubo_control⽇志中 textmsg("joint move to waypoint_1") moveJoint(Waypoint_2_q, 1, 1, 0, 0) textmsg("joint move to waypoint_2") moveJoint(Waypoint_3_q, 1, 1, 0, 0) textmsg("joint move to waypoint_3")
运行程序。
5. 示教器脚本示例
5.1 textmsg函数
使用textmsg()可以打印类型为字符串的信息至aubo_control日志中。其打印信息可在示教器的主页界面中看到。
textmsg的LUA函数定义: textmsg(msg: string) -> nil
用法:
(1)当变量类型为String(字符串)时:-- 获取机器人的名称 name = getName() textmsg(name)
(2)当变量类型为Boolean(布尔值) 时:
-- 机器人是否已经停止下来 is_steady = isSteady() textmsg(tostring(is_steady))
(3)当变量类型为Number(数字) 时:
-- 获取机器人的模式状态 mode_type = getRobotModeType() textmsg("The type of robot mode is "..mode_type)
(4)当变量类型为Table(表) 时:
-- 获取当前的机械臂关节角度 joint_positions = getJointPositions() textmsg(table.concat(joint_positions, ', '))
5.2 TCP/IP通信示例
5.2.1 实现TCP/IP通信的方法
这里有两种方法可以实现机器人和外部设备的socket通信:
方法1是使用Lua的Socket库。
Lua的Socket库是一种通用的网络编程库,允许在Lua脚本中创建Socket连接,进行数据传输和接收。
方法2是使用由遨博提供的Socket类Lua接口。
遨博提供了专门的Socket类脚本接口,允许机器人直接与外部设备进行通信。
5.2.2 遨博的Socket类Lua接口介绍
socketOpen
函数定义:
socketOpen(address: string, port: number, socket_name: string) -> nil
功能:建立TCP/IP以太网socket通信
参数:
- address:目标服务器的IP地址
- port:目标服务器的端口号
- socket_name:socket名称
示例:
socketOpen('192.168.10.46', '8000', "socket_0")
socketSendLine
函数定义:
socketSendLine(str: string, socket_name: string) -> nil
功能:向服务器发送带有换行字符的字符串,以ASCII编码将字符串通过socket发送
参数:
- str:要发送的字符串
- socket_name:socket名称
示例:
socketSendLine("abcd", "socket_0")
socketReadString
函数定义:
socketReadString(variable: string, socket_name: string, prefix: string, suffix: string, interpret_escape: boolean) -> number
功能:从socket中读取所有数据,并将数据作为字符串返回
参数:
- variable:要读取的字符串
- socket_name:socket 名称
- prefix:指定了从socket中提取的子串(消息)的起始位置。从socket中到达 "prefix" 结束的数据将被忽略和移除
- suffix:指定了从socket中提取的子串(消息)的结束位置。在 "suffix" 之后的任何剩余数据将被保留
- interpret_escape:表示是否解释转义字符。如果设置为true,函数会解释字符串中的转义字符(例如'\r'、'\n'、'\t'等),如果设置为false,则不会解释转义字符,而是将其原样返回
示例:
socketReadString("camera", "socket_0", "", "", false)
socketClose
函数定义:
socketClose(socket_name: string) -> nil
功能:关闭与服务器的socket连接
参数:
- socket_name:socket 名称
示例:
socketClose("socket_0")
5.2.3 通过脚本实现TCP/IP通信的操作步骤
操作步骤如下:
确认外部设备与机器人处于同一局域网中,保证双方可以互相ping通(Windows系统建议关闭防火墙)。
以机器人为客户端,外部设备为服务端,方法1和方法2的脚本代码示例分别如下。
方法1:使用Lua的Socket库来实现TCP通信
local socket = require("socket.core") local tcp = socket.tcp() local host = '192.168.10.46' --服务端IP地址 local port = '8000' --串口号 local clicon = tcp:connect(host,port) if(clicon) then textmsg('connect '..host..' ok!') else textmsg('connect error') end take_photo = "get" --发送给服务端的字符串 tcp:settimeout(2) str1 = nil --服务端发送的数据 while (true) do --如果服务端关闭则停止循环 if status =="closed" then textmsg("server is closed!") break end --发送给服务端字符串 tcp:send(take_photo) sleep(1) --接收服务端发送的字符串,只有接收到good,停止循环 s, status, str1 = tcp:receive() if str1 == "good" then textmsg("receive: "..str1) break end end tcp:close()
这段代码的主要作用是机器人与指定的服务端建立TCP连接,然后发送字符串 "get" 给服务端,并且持续接收服务端发送的数据,直到接收到 "good" 字符串为止,最后关闭TCP连接。
方法2:使用由遨博提供的Socket类接口来实现TCP通信
ip = "192.168.10.46" --服务端IP地址 port = 8000 --串口号 client_name = "socket_0" --客户端名称 rec_key = "camera" --接收服务端发送的字符串 socketOpen(ip, port, client_name) ----与服务端建立通信 socketSendLine("abcd", client_name) --发送给服务端字符串 sleep(1) rec_str = "" --接收服务端发送的字符串后停止循环 while(rec_str == nil or rec_str == "") do socketReadString(rec_key, client_name, "", "", false) sleep(0.1) rec_str = getString(rec_key, "") textmsg("**********") textmsg(rec_str) textmsg("**********") sleep(1) socketSendLine("dfgh", client_name) end socketClose(client_name)
这段代码的主要作用机器人是与服务端建立Socket连接,发送一些字符串给服务端,然后循环地接收服务端发送的字符串,直到接收到非空的字符串为止,最后关闭与服务端的socket连接。
以TCP调试助手来模拟服务端,指定服务器的监听端口号为8000。
以机械臂作为客户端,修改方法1或方法2的示例代码中服务器的IP地址和端口号。
在示教器中新建一个脚本模板,运行方法1或方法2中的脚本示例。
注意:运行工程前,请取消勾选”程序一直循环“。
运行结果如下:
方法1:使用Lua的Socket库来实现TCP通信
运行示教器工程后,TCP调试助手会一直接收到机器人发送的“get”字符串。
在TCP调试助手中向机器人发送“good”字符串后,
机器人停止循环发送“get”字符串,并且关闭socket连接。
方法2:使用由遨博提供的Socket类接口来实现TCP通信
运行示教器工程后,TCP调试助手会一直接收到机器人发送的“dfgh”字符串。
在TCP调试助手中向机器人发送一个非空的字符串,例如“stop”后,
机器人停止循环发送“dfgh”字符串,并且关闭socket连接。