还记不记得ROS1中Graph的几个概念?(可以出门左转复习《ROS探索总结(二)——ROS总体框架》)节点、消息、主题、服务,在ROS2里边又新加入了一个“发现(Discovery)”的概念。节点、消息、主题、服务这几个概念这里就不赘述了,在ROS2和ROS1里是相同的,我们来看一下什么叫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。
然后我们回到系统的终端,先来安装一些依赖包:
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到你需要的目录下。进入文件夹,你应该可以看到如下图所示的一些文件。
有没有点熟悉,没错,和ROS1的目录结构几乎一致。
2. 设置环境变量
由于我们下载的是已经编译好的二进制包,不需要编译安装的过程(包括里边的示例代码,talker和listener都已经是编译好的),直接就可以使用了。当然运行前还是要设置一下环境变量(每个终端都需要,或者直接在.bashrc文件里添加):
source setup.bash
3. 执行程序
好啦,终于到最激动人心的运行程序啦,在两个终端中分别执行“talker”和“listener”命令(也许会出现某些错误,不用担心,使用apt-get install统统可以解决),一切顺利的话,你就可以看到如下的界面了:
运行完程序了,是不是有点想看源码,还是老规矩,我们来解析一下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