没有机器人,如何学习ROS编程

来源: 云巴巴 2020-05-08 14:16:01

ROS是目前最流行最全面的机器人操作系统,通过ROS上的编程学习,能够让我们切身体验各种机器人技术如何在现实中进行融合和使用。但是,一台支持ROS的机器人价格不菲,不像手机,说买就买。如果没有机器人,我们就没法学习ROS编程了吗?不可能!什么都不能阻挡我们拥抱ROS的热情和决心!这次就给同学们介绍一个开源的ROS机器人仿真项目,这个仿真项目集成了三维图形界面和物理惯性和碰撞引擎,脱离了物理世界的机器人实体,让我们坐着躺着就能把程序跑在一台ROS机器人上,看着它运动,看着它撞墙,看着它倒地……

一、开源项目网址

https://github.com/6-robot/wpr_simulation

注意:由于Indigo(Ubuntu 14.04)集成的Gazebo版本太过古老,已经失去维护无法使用。建议系统版本为Kinetic/Ubuntu 16.04以上版本。

二、开源项目的下载

在Ubuntu系统中,打开一个终端程序,输入如下指令下载项目源码:

cd catkin_ws/src

git clone https://github.com/6-robot/wpr_simulation.git

没有机器人,如何学习ROS编程

其中“catkin_ws”为ROS的工作空间,请根据电脑的环境设置进行修改。这个项目的源码是从Github网站下载的,所以下载过程需要连接互联网。

源码下载完成后,运行如下指令进行源码工程的编译:

cd ~/catkin_ws

catkin_make

 

没有机器人,如何学习ROS编程

这个开源工程,用到了Gazebo,如果之前安装的ROS是完整版本,则会很顺利的编译通过。如果编译过程中提示缺少某些依赖项,可以通过如下指令补充完整:

sudo apt-get install ros-kinetic-desktop-full

三、开源项目的使用

项目编译完成后,可以通过如下指令启动一个简单的仿真场景:

roslaunch wpr_simulation wpb_simple.launch

没有机器人,如何学习ROS编程

启动后,会弹出一个窗口,里面显示一台机器人,面对着一个柜子发呆:

没有机器人,如何学习ROS编程

这个就是仿真环境的主界面,可以看到界面的周围有很多的工具按钮和菜单列表,这些我们会在后续的教程中进行介绍,这次先跳过,直接进入ROS编程的正题。

四、和ROS程序的连接

仿真环境运行起来了,下面看看如何与ROS程序进行连接。这里准备了一个简单的速度控制程序作为例子,可以运行起来体验一下。保持刚才启动的仿真环境别关闭,在Ubuntu系统中再新打开一个终端,输入如下指令:

rosrun wpr_simulation demo_vel_ctrl

没有机器人,如何学习ROS编程

 

运行之后,可以看到机器人开始向前缓慢移动,直到撞上柜子……

 

没有机器人,如何学习ROS编程

五、示例程序源码解析

这个demo_vel_ctrl就是一个简单的ROS机器人速度控制程序,它的源代码位置:

~/catkin_ws/src/wpr_simulation/src/ demo_vel_ctrl.cpp

我们可以用Visual Studio Code之类的IDE打开这个源码文件:

#include <ros/ros.h>

#include <geometry_msgs/Twist.h>

 

int main(int argc, char** argv)

{

ros::init(argc, argv, "demo_vel_ctrl");

 

ros::NodeHandle n;

ros::Publisher vel_pub = 

n.advertise<geometry_msgs::Twist>("/cmd_vel", 10);

 

while (ros::ok())

{

geometry_msgs::Twist vel_cmd;

vel_cmd.linear.x = 0.1;

vel_cmd.linear.y = 0.0;

vel_cmd.linear.z = 0.0;

vel_cmd.angular.x = 0;

vel_cmd.angular.y = 0;

vel_cmd.angular.z = 0;

vel_pub.publish(vel_cmd);

ros::spinOnce();

}

 

return 0;

}

(1) 代码的开始部分,先include了两个头文件,一个是ros的系统头文件,另一个是运动速度结构体类型geometry_msgs::Twist的定义文件;

(2) ROS节点的主体函数是int main(int argc, char** argv),其参数定义和其他C++程序一样;

(3) main函数里,首先调用ros::init(argc, argv, "demo_vel_ctrl");进行该节点的初始化操作,函数的第三个参数是节点名称;

(4) 接下来声明一个ros::NodeHandle对象n,并用n生成一个广播对象vel_pub,调用的参数里指明了vel_pub将会在主题“/cmd_vel”里广播geometry_msgs::Twist类型的数据。我们对机器人的控制,就是通过这个广播形式实现的。这里就有一个疑问:为什么是往主题“/cmd_vel”里广播数据而不是其他的主题?机器人怎么知道哪个主题里是要执行的速度?
答案是:在ROS里有很多约定俗成的习惯,比如激光雷达数据发布主题通常是“/scan”,坐标系变换关系的发布主题通常是“/tf”,所以这里的机器人速度控制主题“/cmd_vel”也是这样一个约定俗成的情况。

(5) 为了连续不断的发送速度,使用一个while(ros::ok())循环,以ros::ok()返回值作为循环结束条件可以让循环在程序关闭时正常退出。

(6) 为了发送速度值,声明一个geometry_msgs::Twist类型的对象vel_cmd,并将速度值赋值到这个对象里。其中:

(7) vel_cmd.linear.x是机器人前后平移运动速度,正值往前,负值往后,单位是“米/秒”;

(8) vel_cmd.linear.y是机器人左右平移运动速度,正值往左,负值往右,单位是“米/秒”;

(9) vel_cmd.angular.z(注意angular)是机器人自转速度,正值左转,负值右转,单位是“弧度/秒”;

(10) 其他值对启智机器人来说没有意义,所以都赋值为零。

(11) vel_cmd赋值完毕后,使用广播对象vel_pub将其发布到主题“/cmd_vel”上去。机器人的核心节点会从这个主题接收我们发过去的速度值,并转发到硬件底盘去执行。

调用ros::spinOnce()函数给其他回调函数得以执行。

可以看到这是一个标准的ROS程序,在实体机器人上,它实现的是让机器人以0.1米/秒的速度往前推进,在这个仿真环境里,机器人也是执行了相同的行为。

六、和ROS系统工具的连接

在这个仿真环境里,是否可以正常的使用ROS的系统工具?我们来实践一下,启动一个Rviz工具,显示机器人采集到的传感器数据。为了省去繁琐的配置工作,这里我们直接下载一个现成的ROS机器人开源代码。打开一个新的终端程序,输入如下指令:

cd ~/catkin_ws

git clone https://github.com/6-robot/wpb_home.git

 

没有机器人,如何学习ROS编程

下载完成后,再次进行编译:

cd ~/catkin_ws

catkin_make

没有机器人,如何学习ROS编程

保持刚才启动的仿真环境别关闭,在Ubuntu系统新打开一个终端,输入如下指令:

roslaunch wpr_simulation wpb_rviz.launch

没有机器人,如何学习ROS编程

 

运行指令后,就会弹出ROS标配的图形显示界面Rviz,里面显示的就是仿真环境中的虚拟机器人所感知到的各种数据:

 

没有机器人,如何学习ROS编程

 

  • 右侧主界面里显示的是机器人头部的立体相机采集到的三维点云。

  • 柜子底部的红色点阵是机器人底盘激光雷达扫描到的障碍物边缘。

  • 左下角的视频图像是机器人头部彩色相机采集到的数据。

在机器人运动的过程中,上述数据都会实时的变化,可以很直观的测试我们编写的机器人控制程序。

七、基于传感器数据的闭环控制

下面我们再看看一个复杂一点的例子,在一个标准的ROS程序里,获取机器人从仿真环境里采集到的数据,再反馈回去控制仿真环境里的虚拟机器人。整个程序的实现思路:

没有机器人,如何学习ROS编程

从如下地址可以找到这个程序的源代码文件:

~/catkin_ws/src/wpb_home/wpb_home_tutorials/

src/wpb_home_lidar_behavior.cpp

我们可以用Visual Studio Code之类的IDE打开这个源码文件:

#include <ros/ros.h>

#include <std_msgs/String.h>

#include <sensor_msgs/LaserScan.h>

#include <geometry_msgs/Twist.h>

 

ros::Publisher vel_pub;

static int nCount = 0;

 

void lidarCallback(const sensor_msgs::LaserScan::ConstPtr& scan)

{

int nNum = scan->ranges.size();

 

int nMid = nNum / 2;

float fMidDist = scan->ranges[nMid];

ROS_INFO("Point[%d] = %f", nMid, fMidDist);

 

if (nCount > 0)

{

nCount--;

return;

}

 

geometry_msgs::Twist vel_cmd;

if (fMidDist > 1.5f)

{

vel_cmd.linear.x = 0.05;

}

else

{

vel_cmd.angular.z = 0.3;

nCount = 50;

}

vel_pub.publish(vel_cmd);

}

 

int main(int argc, char** argv)

{

ros::init(argc, argv, "wpb_home_lidar_behavior");

 

ROS_INFO("wpb_home_lidar_behavior start!");

 

ros::NodeHandle nh;

ros::Subscriber lidar_sub = nh.subscribe("/scan", 10, &lidarCallback);

vel_pub = nh.advertise<geometry_msgs::Twist>("/cmd_vel", 10);

 

ros::spin();

}

源码解析:

(1) 代码的开头include了四个头文件:ros.h是ros的系统头文件;String.h是字符格式的定义文件,用来做文字输出;LaserScan.h是激光雷达的数据格式定义文件,用来装载雷达数据;Twist.h是机器运动速度消息包的格式定义文件,对应的Twist消息包格式如下:

没有机器人,如何学习ROS编程

其中linear是运动控制的线性分量,也就是机器人直线移动的分量,angular是机器人旋转运动的分量。这两个分量都是Vector3类型,其结构定义如下:

没有机器人,如何学习ROS编程

可见Vector3类型包含三个浮点数:x、y和z。对于linear来说,x、y和z对应的是沿X轴、Y轴和Z轴方向上的速度分量,分量数值单位为“米/秒”。对于angular来说,x、y和z对应的是以X轴、Y轴和Z轴为旋转轴的旋转速度分量,分量数值单位为“弧度/秒”。

(2) 程序接下来定义一个消息发布对象vel_pub,后面会用这个发布对象向机器人核心节点发送速度控制消息包。因为机器人转向行为需要维持一段时间,才能转到完全避开障碍物的方向,所以这里定义了一个int型变量nCount,用来调整机器人转向动作的时长。

(3) 定义一个回调函数void lidarCallback(),用来处理激光雷达数据。ROS每接收到一帧激光雷达数据,就会自动调用一次回调函数。雷达的测距数值会以参数的形式传递到这个回调函数里。

(4) 在回调函数void lidarCallback()中,参数scan是一个sensor_msgs::LaserScan格式的数据包,其数据格式定义如下:

没有机器人,如何学习ROS编程

其中float32[] ranges数组存放的就是激光雷达的测距数值。启智ROS机器人使用的是RPLidar A2型号激光雷达,其旋转一周测量360个距离值,所以在我们的代码里,ranges是一个360个成员的距离数组。

按照程序逻辑,我们需要的是机器人正前方的测距数值,根据激光雷达在机器人上的安装位置,激光雷达的扫描角度如下图所示:

没有机器人,如何学习ROS编程

从图中可知机器人正前方的激光射线角度为扫描角度范围的中间值,我们定义一个变量nNum,用来获取ranges数组的成员个数。再定义一个变量nMid,值为nNum的一半,由上图可知,nMid对应的激光雷达扫描线序即为机器人正前方的扫描线,以nMid作为下标从ranges数组里取到的值即为机器人正前方的雷达测距数值,我们将这个测距值保存到变量fMidDist中。fMidDist中的数值为一个小数,数值单位为“米”。我们使用ROS_INFO()将机器人正前方的雷达测距数值fMidDist显示到终端程序里,方便我们观察和调试。

接下来是对nCount的一个数值判断:如果nCount大于0,则将nCount减一,并直接return中断这个回调函数,让机器人维持之前的运动状态直到nCount递减到0。这就实现了通过给nCount赋值来控制机器人转向动作时长的功能。

程序里定义了一个geometry_msgs::Twist消息包vel_cmd,用来装载我们要发送的机器人运动控制量,然后根据fMidDist的数值大小来对vel_cmd进行不同的赋值。当fMidDist大于1.5时,也就是机器人正前方的障碍物距离大于1.5米的时候,我们给vel_cmd的x赋值0.05,控制机器人以0.05米/秒的速度缓慢向前移动;当fMidDist不大于1.5时,也就是机器人正前方的障碍物距离小于或等于1.5米的时候,我们给vel_cmd的z赋值0.3,控制机器人以0.3弧度/秒的速度原地向左旋转,同时对nCount赋值50,让机器人在后面的50次回调函数执行过程中都维持这个旋转动作。对vel_cmd赋值完毕后,通过vel_pub将其publish发布到相关主题上,启智ROS的核心节点会从主题中获得这个数据包,并按照我们赋值的速度对机器人底盘进行运动控制。

(5) 在主函数main()中,调用ros::init(),对这个节点进行初始化。

(6) 调用ROS_INFO()向终端程序输出字符串信息,以表明节点正常启动了。

(7) 定义一个ros::NodeHandle节点句柄nh,并使用这个句柄向ROS核心节点订阅“/scan”主题的数据,回调函数设置为之前定义的lidarCallback()。

(8) 使用节点句柄nh对vel_pub进行初始化,让其在主题“/cmd_vel”发布速度控制消息,启智ROS的核心节点会从这个主题获取vel_pub发布的消息,并控制机器人底盘执行消息包里的速度值。

(9) 调用ros::spin()对main()函数进行阻塞,保持这个节点程序不会结束退出。

这个程序在前面我们已经编译过了,这里直接执行即可。保持刚才启动的仿真环境别关闭,在Ubuntu系统新打开一个终端,输入如下指令:

rosrun wpb_home_tutorials wpb_home_lidar_behavior

没有机器人,如何学习ROS编程

这条指令会启动刚才的wpb_home_lidar_behavior程序。按照程序逻辑,会从激光雷达的“/scan”主题里不断获取激光雷达数据包,并把机器人正前方的激光雷达测距数值显示在终端程序里。终端里显示“Point[180] = xxxx”其中xxxx为一个浮点数,单位是“米”。比如“Point[180] = 2.626860”表示机器人正前方的激光雷达测距值为2.626860米。

 

没有机器人,如何学习ROS编程

这时切换到仿真环境界面,可以观察机器人的运行效果:

(1) 程序启动后,机器人开始以0.05米/秒的速度向前移动。

(2) 当机器人前方1.5米处出现障碍物时,机器人停止移动,以0.3弧度/秒的速度原地转动。

(3) 当机器人转到前方1.5米范围内没有障碍物时,停止转动,继续以0.05米/秒的速度向前移动。

没有机器人,如何学习ROS编程

八、问题反馈

至此,关于这个仿真项目的简单体验就介绍完了,如果同学们在安装和使用过程中遇到问题,可以在这个项目的Github主页上提交issuse,我们会及时回复,让其他遇到类似问题的小伙伴也能看到。提交issuse的方法:

(1) 在浏览器中打开项目的Github主页:

https://github.com/6-robot/wpr_simulation

(2) 点击分页栏的第二项“Issues”切换页面:

没有机器人,如何学习ROS编程

(3) 在“Issues”页面中点击“New issue”即可提交新的issuse:

没有机器人,如何学习ROS编程

九、后续更新

在这个系列后续的文章里,我们还会详细介绍Gazebo这个仿真环境的使用。同时这个开源项目也会继续持续更新,添加越来越多的新功能,比如SLAM环境建图、路径规划与导航、语音识别、人脸识别、物品识别、物品抓取……等等等等,也欢迎各位同学在“Issues”中给我们新的想法和反馈。

如果你喜欢这个项目,麻烦不要吝啬手中的鼠标,素质三连!赏给我们一颗小星星!您的满意是我们持续更新的最大动力!谢谢~~我们下次再见!(比心❤)

没有机器人,如何学习ROS编程

没有机器人,如何学习ROS编程

更多产品了解

欢迎扫码加入云巴巴企业数字化交流服务群

产品交流、问题咨询、专业测评

都在这里!

 

评论列表

为你推荐

有孚蓝鲸助力企业迈向IT运维新阶段

有孚蓝鲸助力企业迈向IT运维新阶段

 近几年,云计算、大数据、人工智能等IT技术迅猛进展,信息化建设逐步深入,信息系统已成为企业核心竞争力的重要部分,因此,信息技术的运行和维护的保障IT运维,越来越受到人们的重视。随着许多新的IT技术成熟和迅速变化的业务需求,IT运维不断探索新的模式,

2020-04-03 13:33:46

高性能算力来袭!北京发放算力券,降低企业算力使用成本

高性能算力来袭!北京发放算力券,降低企业算力使用成本

该方案支持软件信息服务业企业和制造业企业在多个领域进行行业人工智能大模型训练和应用,并提供算力券补贴支持,降低企业智能算力使用成本。

2024-03-27 15:01:19

什么是人脸识别?人脸识别备受追捧的原因有哪些

什么是人脸识别?人脸识别备受追捧的原因有哪些

首先让我们了解一下什么是人脸识别,是人工智能范畴里,生物识别中的一个类别,人体的生物特征具有唯一性和不易被复制的良好特性,人脸与人体的其它生物特征(指纹、虹膜等)一样与生俱来,为身份鉴别提供了必要的前提。

2022-11-23 15:58:14

深入浅出,带你了解Apollo技术

深入浅出,带你了解Apollo技术

Apollo中的控制算法由一个或多个控制器组成,可以轻松更改或替换为不同的算法。 每个控制器将一个或多个控制命令输出到CANbus。

2019-09-18 15:51:01

人脸识别的应用前景能给我们带来哪些启示

人脸识别的应用前景能给我们带来哪些启示

生物计量技术已广泛应用于政府、军事、银行、社会福利保障、电子商务、安全和国防等领域。

2020-04-13 20:21:16

虹膜识别与指纹识别相比因这些优势被我们选择

虹膜识别与指纹识别相比因这些优势被我们选择

虹膜识别技术从出现在我们身边再到飞速发现,越来越多的领域内都用到了虹膜识别技术,而且和安全相关的设施更是把利用虹膜识别技术作为身份认证的主要选择,虹膜识别技术也和指纹识别技术、面部识别技术一起成为了进行身份认证的主要方式。而虹膜识别技术和指纹识别技术以及面

2022-11-24 10:33:26

严选云产品

科大讯飞语音调度系统 通过讯飞语音识别技术,精准命中调度指令,结合NLP语义理解,将文本信息转换成机器指令传入系统,进行具体事项操作,同时还可以加入TTS语音合成技术,在执行指令时,进行状态播报,以达到人机交互,准确把控指令操作。
晓多科技售后机器人 晓多科技售后机器人订单信息自动获取,登记效率提升。工单创建重复校验,避免客服重复处理。手淘小程序买家自反馈,释放客服处理时效。打通旺店通、万里牛,实现创建补发单直接同步至ERP,可选择是否直接审核通过。工单处理完结可以触发话术给买家,减少买家二次售后咨询。企业级数据纵览。工单处理时效、工单满意度数据沉淀,辅助客服绩效考核。
XE3000软件定义存储一体机 XSKY星辰天合提供的SDS (软件定义存储)一体机-XSCALER3000,是面向大规模存储应用的软件定义存储一体机,将领先的软件定义存储技术和丰富的最佳实践相结合,以高性能、高可扩展、高可靠的存储产品助力用户轻松构建存储云。
万兴科技万兴PDF编辑器 万兴PDF采用类似Word界面和工具条设计,集格式转换、 再编辑、分发、加解密、阅读、修改、批注、填表单、电子签名、水印等功能于一体,具有易操作、高效、功能全等特征,帮助全球超过50万家企业不再依赖 Adobe®Acrobat®。
百度智能云税务识别系统 百度智能云税务识别系统,拥有七大产品核心模块,单证对比管理,单据规则管理,单据要素管理,单据类型管理,单据模板管理,单据对比日志,数据可视化,极大的提高了业务人员的录入和核检的工作效率。
天翼云云桌面系统 云桌面基于虚拟化技术对物理设备进行虚拟化处理,将Windows/Linux/安卓桌面及其应用提供给用户。通过云桌面,用户可以通过多种设备(包括台式机、笔记本 、iOS/Android终端、瘦客户机等)访问桌面,实现计算机功能。

甄选10000+数字化产品 为您免费使用

申请试用