ROS2探索总结(三)——小试牛刀

16369
7
2017年1月24日 12时08分

        看了之前ROS2的框架设计,是不是对ROS2产生了很多好奇。相比ROS1,ROS2中融入了很多新的东西,但是很多核心的概念并没有改变。
 
一、ROS中的Graph

        还记不记得ROS1中Graph的几个概念?(可以出门左转复习《ROS探索总结(二)——ROS总体框架》)节点、消息、主题、服务,在ROS2里边又新加入了一个发现(Discovery)的概念。节点、消息、主题、服务这几个概念这里就不赘述了,在ROS2和ROS1里是相同的,我们来看一下什么叫Discovery。

        我们从前边的框架中已经看到了,ROS2里是没有master的,那么节点之间是怎么知道彼此存在的呢?这就全靠一种自动发现的机制——Discovery。什么意思呢?简单来说,当一个节点启动后,首先在网络中发条广播,大声告诉这个世界我来了(忽然想到三体里人类向宇宙发送广播,招来了外星人。。。),其他节点听到之后,也纷纷反馈各自的信息,这样一来二去也就联系上了。当然,万一哪个节点掉线了怎们办?没关系,每个节点都会周期性的发布广播,告诉其他节点他还在线,就算要下线,他也会广播告诉其他节点他要走了,下次再聊。
 
二、小试牛刀

        看了这么多概念,一时不一定消化得了,让我们小试牛刀,加强一下印象。从哪里下手呢?还记不记得ROS wiki上最初的talker and listener,ROS2还是继续从这里出发。

        1. 安装ROS2

        说了这么多,我们好像还没有安装ROS2吧,那就看一下怎么安装。

        目前ROS2还处于开发阶段,提供两种安装方法:二进制包和源码编译。我们还是偷偷懒,直接使用编译好的二进制包。打开网站https://github.com/ros2/ros2/releases,找到最新发布的ROS版本,目前最新版是Beta1,看看下载列表,是不是很激动的可以看到linux、osx、windows三个版本的二进制包,支持的平台确实比ROS1多了吧。不过我们还是从熟悉的Linux环境开始,需要Ubuntu16.04,从列表中下载ros2-beta1-package-linux-fastrtps.tar.bz2

Image[8]

          然后我们回到系统的终端,先来安装一些依赖包:

sudo apt-get update && sudo apt-get install -q -y \
    libopencv-core2.4v5 \
    libhighgui2.4 \
    libopencv-imgproc2.4v5 \
    wget

         接着,解压刚才下载的ros2-beta1-package-linux-fastrtps.tar.bz2到你需要的目录下。进入文件夹,你应该可以看到如下图所示的一些文件。

Image(1)[8]

        有没有点熟悉,没错,和ROS1的目录结构几乎一致。

          2. 设置环境变量

        由于我们下载的是已经编译好的二进制包,不需要编译安装的过程(包括里边的示例代码,talker和listener都已经是编译好的),直接就可以使用了。当然运行前还是要设置一下环境变量(每个终端都需要,或者直接在.bashrc文件里添加):

source setup.bash

3. 执行程序

         好啦,终于到最激动人心的运行程序啦,在两个终端中分别执行talkerlistener命令(也许会出现某些错误,不用担心,使用apt-get install统统可以解决),一切顺利的话,你就可以看到如下的界面了:

Image[8]
         久违的感觉了,有没有!两个节点成功连接上,而且并没有master的参与,这就是“神奇”的Discovery机制。
 
三、源码剖析

        运行完程序了,是不是有点想看源码,还是老规矩,我们来解析一下ROS2中的talker和listener到底有什么不同。talker和listener的源码在:https://github.com/ros2/tutorials

        1. talker

#include <iostream>
#include <memory>

#include "rclcpp/rclcpp.hpp"
#include "std_msgs/msg/string.hpp"

int main(int argc, char * argv[])
{
  //ros::init(argc, argv, "talker");
  rclcpp::init(argc, argv);

  //ros::NodeHandle n;
  auto node = rclcpp::node::Node::make_shared("talker");

  rmw_qos_profile_t custom_qos_profile = rmw_qos_profile_default;
  custom_qos_profile.depth = 7;

  //ros::Publisher chatter_pub = n.advertise<std_msgs::String>("chatter", 1000);
  auto chatter_pub = node->create_publisher<std_msgs::msg::String>("chatter", custom_qos_profile);

  //ros::Rate loop_rate(10);
  rclcpp::WallRate loop_rate(2);

  auto msg = std::make_shared<std_msgs::msg::String>();
  auto i = 1;

  //while (ros::ok())
  while (rclcpp::ok()) {
    msg->data = "Hello World: " + std::to_string(i++);
    std::cout << "Publishing: '" << msg->data << "'" << std::endl;

    //chatter_pub.publish(msg);
    chatter_pub->publish(msg);

    //ros::spinOnce();
    rclcpp::spin_some(node);

    //loop_rate.sleep();
    loop_rate.sleep();
  }

  return 0;
}
 

        2. listener

#include <iostream>
#include <memory>

#include "rclcpp/rclcpp.hpp"
#include "std_msgs/msg/string.hpp"

//void chatterCallback(const std_msgs::String::ConstPtr& msg)
void chatterCallback(const std_msgs::msg::String::SharedPtr msg)
{
  std::cout << "I heard: [" << msg->data << "]" << std::endl;
}

int main(int argc, char * argv[])
{
  //ros::init(argc, argv, "listener");
  rclcpp::init(argc, argv);

  //ros::NodeHandle n;
  auto node = rclcpp::Node::make_shared("listener");

  //ros::Subscriber sub = n.subscribe("chatter", 1000, chatterCallback);
  auto sub = node->create_subscription<std_msgs::msg::String>(
    "chatter", chatterCallback, rmw_qos_profile_default);

  //ros::spin();
  rclcpp::spin(node);

  return 0;
}

       我在每句的代码上用注释标注了对应于ROS1中的代码,便于大家比较。仔细阅读上边的代码,我们可以从以下几点做出对比分析:

1. ROS2中的API相比ROS1中发生了较大的变化,这和ROS2设计文档中描述的一致,ROS2并不是在ROS1的基础上查漏补缺,而是完全从新设计。关于ROS2的API说明,可以参考API文档:http://docs.ros2.org/beta1/api/rclcpp/index.html

2. 使用了更多C++的特性,比如auto、make_shared等。

3. 加入了QoS配置,从上边的代码中,我们可以看到QoS有默认的配置rmw_qos_profile_default ,而且talker将QoS的depth配置设置为7

4. 代码的总体架构还是与ROS1极为相似的。

参考资料:

Overview of ROS 2 concepts : https://github.com/ros2/ros2/wiki/Overview-of-ROS-2-concepts

C++ ROS Client Library API:http://docs.ros2.org/beta1/api/rclcpp/index.html

发表评论

后才能评论

评论列表(7条)

  • zhou 2019年2月25日 下午3:54

    auto node = rclcpp::node::Node::make_shared(“talker”) -> auto node = rclcpp::Node::make_shared(“talker”);

  • 罗西 2018年4月8日 上午11:12

    月哥,如果在之前安装ros1的基础上再安装ros2,这两者冲突吗?

    • 古月 回复 罗西 2018年4月9日 上午10:06

      不冲突的

    • 李晓冬 回复 古月 2019年4月1日 上午8:50

      老师,我在安装完ros2后一直报”ROS_DISTRO was set to ‘kinetic’ before. Please make sure taht the environment does not mix paths from different distributions.”这个环境变量应该怎么设置,因为我编译ROS2的代码时,还是默认使用的是kinetic编译的

    • 古月 回复 李晓冬 2019年4月1日 上午9:54

      两个编译系统不一样,不能混用,环境变量还是在.bashrc里边设置,最好不要ROS1和ROS2的环境变量同时开启

  • liufanghua 2017年10月18日 上午11:34

    这里下载的ROS2安装包带了DDS么?运行的例程是否需要DDS的支持?