引言

最近项目中遇到一个需求:将 C++ 程序 (不是 ROS node,只是普通的 C++ 程序)中的变量发布到 ROS topic 上,以便 ROS 中的其他 node 进行后续处理。

原 C++ 程序比较复杂,我们希望尽量少修改原程序,只要输出其中某些变量的值即可,不要大规模改写成 ROS node 的形式,不要新建 ROS package。

在以往使用 ROS 的过程中,我们一般是借助 catkin 来编译 ROS node C++ 程序。这可以看成是将 C++ 程序放入 ROS 框架中,以 ROS 的标准形式来编译。现在这个项目需求正好相反,我们要将 ROS 的相关库(library)嵌入到普通 C++ 程序中,采用 C++ 标准的 cmake 方式来编译。这就要求我们对 cmake 和 catkin 的关系有比较深入的了解。

在查找资料的过程中,我们发现了一篇讲解 catkin 编译系统的文章,从最基本的命令行编译方式,到 makefile 文件编译,再到 catkin 编译,每一步发展的必要性都讲解的很清楚,看完之后,我们对 catkin 有了更深入的认识。

本文是一篇学习笔记,也可以看成是对原文的意译。

对原文感兴趣的读者可以移步这里 http://jbohren.com/tutorials/2014-02-12-gentle-catkin-intro/

预安装

原文例子中使用了 hydro 版本的 ROS,现在看来比较古老了,这里替换为 kinetic 版本。

  • Ubuntu 16.04
  • ROS kinetic (base 即可)

从最简单的例子开始

首先创建一个文件夹 hello_world_tutorial,存放我们的程序

mkdir hello_world_tutorial
cd hello_world_tutorial

创建 C++ 源文件,名为 hello_world_node.cpp

// 为了与 ROS 交互,需要调用 ROS C++ APIs
#include <ros/ros.h> // 标准的 C++ main 函数
int main(int argc, char** argv) { // 该命令告诉 ROS 初始化了一个 node,名为 hello_world_node
ros::init(argc, argv, "hello_world_node"); // 在一般的 ROS node 程序中,我们会用 ros::NodeHandle nh 来启动 node 程序,
// ros::NodeHandle nh 默认会调用 ros::start() 函数,程序关闭时也会自动调用 ros::shutdown() 函数。
// 我们也可以直接通过 ros::start() 和 ros::shutdown() 来手动控制 node 的开启和关闭
ros::start(); // 显示 hello, world! 信息
ROS_INFO_STREAM("Hello, world!"); // 用 ros::spin() 保持该程序运行,一直等待处理 subscribe 的数据
// 由于该程序并没有 sub,所以就是简单的保持程序不退出而已, 直到接受到终止信号 SIGINT (ctrl-c)
ros::spin(); // 关闭 node 程序
ros::shutdown(); // 结束主程序
return 0;
}

下边将 C++ 源文件编译成可执行文件

g++ hello_world_node.cpp -o hello_world_node -I/opt/ros/kinetic/include -L/opt/ros/kinetic/lib -Wl,-rpath,/opt/ros/kinetic/lib -lroscpp -lrosconsole

各参数含义

  • -I<dir> 指定头文件的搜索路径
  • -L<dir> 指定静态库的搜索路径
  • -Wl,-rpath,/opt/ros/kinetic/lib 指定共享库的搜索路径
  • -lroscpp -lrosconsole 指定需要链接的具体的库文件

编译之后,生成 hello_world_node 可执行文件。由于程序中生成了 ROS node,而 ROS node 需要与 ROS master 进行通讯注册,否则会报错。因此为了正常运行程序,需要先开启 ROS master

roscore

然后运行 hello_world_node

./hello_world_node

如果一切顺利,应该显示类似如下信息:

[ INFO] [1561908777.116073864]: Hello, world!

上述编译方式扩展性很差,对于如此简单的 hello_world 程序,需要设置的参数已经这么多了。而且在 terminal 中书写比较麻烦,修改也不方便。

上面是使用g++编译器直接在终端中对源文件进行编译,通过上面的过程了解到,当编译的源文件需要链接其他库文件、头文件时需要额外添加命令以及文件路径,这样当需要链接的文件比较多时或者编译文件进行修改重新编译时,非常不方便,如果能在脚本文件中将编译命令以及链接文件的路径全部链接到,然后在终端直接执行这个脚本文件岂不是更加方便。因此前人进行了改进

改进:使用 Makefile 文件进行编译

catkin编译系统的更多相关文章

  1. (转)-编写第一个ROS(创建工作空间workspace和功能包package)

    原文网址:http://www.cnblogs.com/liuamin/p/5704281.html 刚接触ROS,学着写了第一个程序,怕以后忘记,就将其步骤记录下来.. 首先你必须保证你电脑已安装配 ...

  2. 编写第一个ROS(创建工作空间workspace和功能包package)

    刚接触ROS,学着写了第一个程序,怕以后忘记,就将其步骤记录下来.. 首先你必须保证你电脑已安装配置好ROS. 1.创建工作空间(workspace) 我们所创建功能包package,应该全部放到一个 ...

  3. ROS入门学习

    ROS学习笔记 ROS入门网站; ROS入门书籍 ROS主要包含包括功能包.节点.话题.消息类型和服务; ROS功能包/软件包(Packages) ROS软件包是一组用于实现特定功能的相关文件的集合, ...

  4. cmake 总结

    cmake中一些预定义变量 PROJECT_SOURCE_DIR 工程的根目录 PROJECT_BINARY_DIR 运行cmake命令的目录,通常是${PROJECT_SOURCE_DIR}/bui ...

  5. 第3章 编写ROS程序-1

    1.创建工作区和功能包 在我们写任何程序之前,第一步是创建一个容纳我们的功能包的工作区,然后再创建功能包本身. 创建工作区  使用标准的mkdir命令行去创建一个目录,我们将把这个新的目录称作工作区目 ...

  6. ROS学习笔记三:编写第一个ROS节点程序

    在编写第一个ROS节点程序之前需要创建工作空间(workspace)和功能包(package).   1 创建工作空间(workspace) 创建一个catkin_ws: #注意:如果使用sudo一次 ...

  7. ROS机器人开发实践学习笔记3

    摘要: 刚刚开始学习ROS,打算入机器人的坑了,参考教材是<ROS及其人开发实践>胡春旭编著 机械工业出版社 华章科技出品.本来以为可以按照书上的步骤一步步来,但是,too young t ...

  8. ros工作空间中文件夹结构

    ROS 编译系统 catkin 详解 ros系统学习之Catkin编译系统 ROS--catkin编译系统.package.xml和CMakeList.txt文件 1.build:编译空间 存放CMa ...

  9. ROS编译:catkin简析

    博客转载自:https://blog.csdn.net/zyh821351004/article/details/50388429 Catkin tutorials: http://wiki.ros. ...

随机推荐

  1. 如何设置计算机IP地址

    今天公司变更网络环境让同学们设置IP地址,我竟然不会,我问了一句IP还能自己设置啊,.low爆了,于是赶紧百度,现总结如下 IP地址的设置一种是静态IP,一种是自动获取IP(之前都是自动获取的吧,而且 ...

  2. 安装xpath helper方便进行爬虫

    安装xpath helper方便进行爬虫 因为我使用的是edge浏览器,扩展商店搜索不到xpath-helper,但是我不甘心,取下载源扩展直接放在edge中试试 下载XPath helper的源码 ...

  3. 面试官:Redis中字符串的内部实现方式是什么?

    在面试间里等候时,感觉这可真暖和呀,我那冰冷的出租屋还得盖两层被子才能睡着.正要把外套脱下来,我突然听到了门外的脚步声,随即门被打开,穿着干净满脸清秀的青年走了进来,一股男士香水的淡香扑面而来. 面试 ...

  4. Docker安装与基本命令使用

    1. 卸载旧版本 Docker在CentOS上的安装 官方文档:https://docs.docker.com/engine/install/centos/ sudo yum remove docke ...

  5. 矩池云上使用nvidia-smi命令教程

    简介 nvidia-smi全称是NVIDIA System Management Interface ,它是一个基于NVIDIA Management Library(NVML)构建的命令行实用工具, ...

  6. Hystrix&Dashboard配置使用

    目录 Hystrix是什么 熔断 什么是熔断 熔断类型 打开 半开 关闭 使用方法 导包 添加启动注解 新增方法 测试 降级 什么是降级 使用方法 导包 修改yml,新增如下 启动类新增注解 @Ena ...

  7. 构造方法__construct()与析构方法__destruct() 构造方法:刚出生时婴儿的啼哭 析构方法:老人临终时的遗言

    <?phpclass person{ var $name; var $sex; var $age;//构造方法 function __construct($name, $sex, $age) { ...

  8. rsyn的使用

    以下是rsync的语法: Local: rsync [OPTION...] SRC... [DEST] Access via remote shell: Pull: rsync [OPTION...] ...

  9. 分布式 PostgreSQL 集群(Citus)官方示例 - 时间序列数据

    在时间序列工作负载中,应用程序(例如一些实时应用程序查询最近的信息,同时归档旧信息. https://docs.citusdata.com/en/v10.2/sharding/data_modelin ...

  10. stash —— 一个极度实用的Git操作

    今天要介绍的 Git 操作就是 stash,毫不夸张地说,每个用 Git 的开发人员都一定要会懂怎么使用. 在介绍之前,不知道你有没有和我一样的经历:某一天,我正在一个 feature 分支上高高兴兴 ...