平台
操作系统:Ubuntu18.04
、Windows 10
操作平台:Barrett
七自由度机械臂
Web
前端框架:Node.js
+ Vue.js
+ Element UI
ROS
与Web
开发工具:Robot Web Tools(roslibjs+ros2djs+ros3djs)
开发工具:Visual Studio Code
服务器:Tomcat8.5
环境搭建
基础环境搭建
参照基于Vue.js的ROSWeb环境搭建
文档。
ROSWeb工具简介
ros-web
是ros
官方提供的从ros
到web
端的一个开源接口。其主要的功能库有3个,即roslibjs
基本库,ros2djs
2D库和ros3djs
3D库。本项目主要用的是roslibjs
和ros3djs
。
roslibjs
库文件
roslibjs
库是ros-web
中的基础库,可以实现创建ROS
,订阅消息、发布话题和调用服务等功能。其中比较重要的类有ROS
、Topic
和Service
。
ROS
类
从ROS
类的源码中可以看出,其底层也是基于socket
协议实现的ros
与web
连接。ROS
类在定义时,只需要提供ros
端的IP
和端口号即可(需要和rosbridge
部分对应),如:1
2
3var ros = new ROSLIB.Ros({
url: 'ws://192.168.*.*:9090'
})
定义完该类后,可以使用ros.on()
函数实时监听ros
的系统状态。Ros
类一共提供了3种状态,即connection
、error
和close
,分别对应连接成功、连接错误和关闭连接状态。在对应的回调函数里面可以编写相应的逻辑功能。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28this.ros.on('connection', () => {
this.$message({
message: '连接成功!',
type: 'success'
})
})
this.ros.on('error', (e) => {
this.$message.error('连接失败!')
})
this.ros.on('close', () => {
this.$message.error('关闭连接!')
})
```
### `Topic`类
```js
var wamPost = new ROSLIB.Topic({
ros: ros,
name: '/wam/pose',
messageType: 'geometry_msgs/PoseStamped'
})
wamPost.subscribe((message) => {
console.log(message)
wamPost.unsubscribe()
})
Topic
类的构造函数需要给定3个参数,即ros
类实例,话题名称name
和话题的消息格式messageType
。实例化类后,即可调用subscribe()
函数订阅话题,并通过回调函数里面的messgage
值获取话题信息,在回调函数中可以使用unsubscribe()
函数取消订阅。1
2
3
4
5
6
7
8var cmdVel = new ROSLIB.Topic({
ros: ros,
name: '/turtle1/cmd_vel',
messageType: 'geometry_msgs/Twist'
})
geometryMsgsTwist.linear.x = 1
cmdVel.publish(geometryMsgsTwist)
除了可以订阅话题并获取信息,还可以发布话题。实例化话题类的方法和订阅一样,但需要提前定义好需要发布的话题消息格式和内容。1
2
3
4
5
6
7
8
9
10
11
12var geometryMsgsTwist = new ROSLIB.Message({
linear: {
x: 0.0,
y: 0.0,
z: 0.0
},
angular: {
x: 0.0,
y: 0.0,
z: 0.0
}
})
消息的定义为对象类型的键值对数据,需要根据实际话题的消息类型来具体定义。
定义好要发送的话题消息数据后,使用publich()
发布话题。这里不需要订阅话题。
Service
类
1 | var setPenClient = new ROSLIB.Service({ |
Service
类的构造函数也需要给定3个参数,即ros
类实例,服务名称name
和服务的消息格式serviceType
。这里同样需要先定义好服务的请求信息,格式为对象类型的键值对数据。实例化服务类后,可以通过callService()
函数调用服务。
ros3djs
库文件
ros3djs
用于可视化3D
模型相关的功能。其中比较重要的类有Viewer
、TFClient
和UrdfClient
等。阅读底层代码可以发现,ros3djs
是基于three.js
3D
库实现的。
Viewer
类
1 | var viewer = new ROS3D.Viewer({ |
Viewer
用于创建一块用于显示3D模型的可视化区域。需要的参数为html
的div
区域ID
divID
,区域的宽度width
,区域的高度heigh
,是否抗锯齿antialias
和背景颜色background
等信息。实例化类后,即可在网页中看到一块空白区域。如需添加网格,调用ddObject(new ROS3D.Grid())
函数即可。
TFClient
类
1 | var tfClient = new ROSLIB.TFClient({ |
TFClient
类是一个基础类,后续的一些类的参数经常需要使用它,构造函数的参数值按照官网提供的参数值即可,其中比较重要的一个参数是fixedFrame
参数,这里需要和urdf
模型中的基础坐标系相对应,否则会出现模型加载不完整,无法控制移动等问题。
UrdfClient
类
1 | var urdfClient = new ROS3D.UrdfClient({ |
UrdfClient
类可以可视化ros
中的urdf
模型,其主要的参数有实例化的ros
,实例化的tfClient
,模型存放的路径path
,根对象rootObject
(即urdf
放在哪个区域)和模型加载器loader
。这里比较重要的参数为path
路径参数,这里存放的是网络或者本地的模型链接地址,本项目使用的vue.js
前端框架,http://localhost:8080
网址对应的即为整个项目文件夹的根目录,因此实际的模型地址位于http://localhost:8080/static
中(需要将模型放在该文件夹下)。
设计思想
界面设计
整体界面分为3个部分,上面为logo
显示和一些常用的功能选项。下面左侧为WAM
3D
模型的可视化显示,右侧为功能逻辑部分,主要测试一些简单的基础功能。
其中WAM
模型在连接成功会实时显示当前的位姿,数据也会实时更新在右下方的表格中。拖动右侧的滑动也会实时更新WAM
的位姿状态。
逻辑功能
ROS
中常见的功能主要有订阅消息
、发布话题
和调用服务
。另外还需要将3D
模型能够可视化显示在web
网页中。因此本项目主要实现的逻辑功能包括:
- 订阅消息(
Subscribing message
) - 发布话题(
publishing topic
) - 调用服务(
Calling service
) - 针对
urdf
和xacro
文件的3D
模型可视化
代码模块
添加依赖文件
在vue.js
的静态文件夹static
中新建文件夹rosweb
,用于存放所需要的第三方JavaScript
文件。
其中roslib.js
和ros3d.js
为ros-web
提供的库文件,剩余JavaScript
文件为用于绘制3D
可视化模型的库文件(主要为three.js
框架及其依赖库)。
然后在index.html
入口文件中,将这些文件添加<head>
标签中。1
2
3
4
5
6<script src="./static/rosweb/three.js"></script>
<script src="./static/rosweb/ColladaLoader.js"></script>
<script src="./static/rosweb/STLLoader.js"></script>
<script src="./static/rosweb/eventemitter2.min.js"></script>
<script src="./static/rosweb/roslib.js"></script>
<script src="./static/rosweb/ros3d.js"></script>
由于ros-web
的ros3d.js
库文件在加载3D
模型时,需要本地或者网络的模型链接,因此需要将ros
中的模型部分放在static
文件夹中。这里将barrett_ros
中的barrett_model
部分添加至static
文件夹中:
主界面功能实现
代码文件位于src->components->HelloWorld.vue
。基本按照ROSWeb工具简介
解释的部分,更改为实际的话题/服务和消息的数据类型即可。
常见问题整理
- 在
index.html
中导入完js
文件,需要在.eslintrc.js
中的rules.globals
声明全局变量:1
2
3
4
5
6
7
8
9
10
11
12
13// add your custom rules here
rules: {
// allow async-await
'generator-star-spacing': 'off',
// allow debugger during development
'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off',
'no-unused-vars': 'off'
},
"globals":{
"THREE": true,
"ROSLIB": true,
"ROS3D": true,
}
否则会出现无法找到该变量的定义的问题。
回调函数要改用为箭头函数,这样就可以使用使用
this
对象了。解析订阅话题的接收到的值时,需要根据实际的格式对其解析。
如果遇到
ctrl+c
关闭节点后,节点仍然存在的问题:在环境变量中添加export ROS_HOSTNAME=hostname
(输入指令hostname
即可查看自己的),且在关闭节点时不要使用ctrl+c
,直接关闭窗口。连续发布多个话题或调用多个服务时,只会执行最后一个。这是
ros
系统的问题,话题是异步通讯机制,发布相同消息时,只会处理最后一个,服务是同步通讯机制,可以通过判断返回的信息来实现依次调用相同的多个服务。