在编写第一个ROS节点程序之前需要创建工作空间(workspace)和功能包(package)。

一、创建工作空间(workspace)

创建一个catkin_ws:

#注意:如果使用sudo一次性创建多个目录,则这多个目录属主都为root,若是非root用户创建的ROS,则无法在root目录创建工作空间
sudo mkdir -p ~/dev/catkin_ws/src
cd ~/dev/catkin_ws/src
catkin_init_workspace

当我们创建工作空间文件夹后,里面并没有功能包,只有CMakeList.txt。下一步是编译工作空间,使用下面命令:

cd ~/dev/catkin_ws
catkin_make

现在,如果你输入ls -l命令,可以看到上面命令创建的新文件夹,分别是“build”和一个“devel”文件夹:

zlkj@ubuntu:~/dev/catkin_ws$ ls -l
total 12
drwxrwxr-x 7 zlkj zlkj 4096 Mar 19 12:10 build
drwxrwxr-x 3 zlkj zlkj 4096 Mar 19 12:10 devel
drwxrwxr-x 2 zlkj zlkj 4096 Mar 19 11:23 src zlkj@ubuntu:~/dev/catkin_ws/build$ ls -l
total 64
drwxrwxr-x 3 zlkj zlkj 4096 Mar 19 12:10 catkin
drwxrwxr-x 4 zlkj zlkj 4096 Mar 19 12:10 catkin_generated
-rw-rw-r-- 1 zlkj zlkj 0 Mar 19 12:10 CATKIN_IGNORE
-rw-rw-r-- 1 zlkj zlkj 125 Mar 19 12:10 catkin_make.cache
-rw-rw-r-- 1 zlkj zlkj 16071 Mar 19 12:10 CMakeCache.txt
drwxrwxr-x 9 zlkj zlkj 4096 Mar 19 12:10 CMakeFiles
-rw-rw-r-- 1 zlkj zlkj 7365 Mar 19 12:10 cmake_install.cmake
-rw-rw-r-- 1 zlkj zlkj 284 Mar 19 12:10 CTestTestfile.cmake
drwxrwxr-x 3 zlkj zlkj 4096 Mar 19 12:10 gtest
-rw-rw-r-- 1 zlkj zlkj 8578 Mar 19 12:10 Makefile
drwxrwxr-x 2 zlkj zlkj 4096 Mar 19 12:10 test_results zlkj@ubuntu:~/dev/catkin_ws/devel$ ls -l
total 36
-rwxr-xr-x 1 zlkj zlkj 506 Mar 19 12:10 env.sh
drwxrwxr-x 2 zlkj zlkj 4096 Mar 19 12:10 lib
-rw-r--r-- 1 zlkj zlkj 260 Mar 19 12:10 setup.bash
-rw-r--r-- 1 zlkj zlkj 2542 Mar 19 12:10 setup.sh
-rwxr-xr-x 1 zlkj zlkj 12378 Mar 19 12:10 _setup_util.py
-rw-r--r-- 1 zlkj zlkj 270 Mar 19 12:10 setup.zsh

可以看到在devel目录下,有很多setup.*sh文件,读取这些文件中的任何一个都会将当前工作空间的环境变量置于所有环境变量的最上层。如果我们打开这些文件会发现,最终都是要读取setup.bash文件,这个文件中定义了catkin_ws空间所需要的环境变量。

读取setup.bash文件:

source devel/setup.bash

确认已经加载好catkin工作空间环境变量:

echo $ROS_PACKAGE_PATH

//显示出:
/home/zlkj/catkin_ws/src:/opt/ros/indigo/share:/opt/ros/indigo/stacks

这时ROS的工作空间已经创建好了。

总结:

初始化ROS的catkin工作空间:catkin_init_workspace

编译ROS的catkin工作空间:catkin_make

读取当前catkin工作空间的环境变量:source devel/setup.bash

验证ROS工作空间的环境变量加载成功:echo $ROS_PACKAGE_PATH

二、创建功能包(package)

使用catkin_create_pkg命令行工具在之前创建的工作空间创建新的功能包:

cd ~/dev/catkin_ws/src
catkin_create_pkg amin std_msgs roscpp

其实,这个功能包创建命令没有做太多工作,它只不过创建了一个存放这个功能包的目录(也就是我所创建的功能包amin),并在amin那个目录下生成了两个配置文件。

  • 第一个配置文件,叫做 package.xml,称为清单文件。
  • 第二个文件,叫做 CMakeLists.txt,是一个 Cmake 的脚本文件,Cmake 是一个符合工业标准的跨平台编译系统。这个文件包含了一系列的编译指令,包括应该生成哪种可执行文件,需要哪些源文件,以及在哪里可以找到所需的头文件和链接库。当然,这个文件表明 catkin 在内部使用了 Cmake。

catkin_create_pkg命令的格式包括功能包的名称和依赖项。在上面示例中,依赖项为std_msgs和roscpp。如以下命令行所示:

catkin_create_pkg [package_name] [depend1] [depend2] [depend3]

这些依赖项包括:

  • std_msgs 包含了常见消息类型,表示基本数据类型和其他基本的消息构造,如多维数组。
  • roscpp 使用C++实现ROS的各种功能。它提供了一个客户端库,让C++程序员能够调用这些接口快速完成与ROS的主题、服务和参数相关的开发工作。

注意:ROS 功能包的命名遵循一个命名规范,只允许使用小写字母、数字和下划线,而且首字符必须是一个小写字母。一些 ROS工具,包括 catkin,不支持那些不遵循此命名规范的功能包。

三、编写ROS节点程序

编写一个简单的ros节点程序,命名为hello.cpp。这个名为 hello.cpp 的源文件也存放在你的功能包 amin文件夹中 , 挨着 package.xml 和 CMakeLists.txt。

注意:一些在线教程建议在你的功能包目录中创建 src 目录来存放 C ++源文件。这个附加的组织结构可能是有益的,特别是对于那些含有多种类型文件的较大的功能包,但它不是严格必要的。

ROS节点程序如下:

#include <ros/ros.h>

int main (int argc, char **argv)
{
ros::init(argc, argv, "hello") ;
ros::NodeHandle nh;
ROS_INFO_STREAM("Hello, ROS!") ;
}

四、编译Hello.cpp程序

我们该如何编译和运行这个程序呢?这些交给ROS的catkin编译系统来处理。

第一步:声明依赖库

首先,我们需要声明程序所依赖的其他功能包。对于 c++程序而言,此步骤是必要的,以确保 catkin 能够向 c++编译器提供合适的标记来定位编译功能包所需的头文件和链接库。

为了给出依赖库,需要编辑功能目录下的 CMakeLists.txt 与 package.xml 文件,通过使用build_depend (编译依赖)和 run_depend(运行依赖)两个关键字实现,格式如下:

<build_depend>package-name</build_depend>
<run_depend>package-name</run_depend>

不过这一步可以省略,因为在创建功能包说明依赖项的同时,系统自动声明了依赖库,除非创建时未说明依赖项。

使用rospack depend1 amin可以查看直接功能包的直接依赖。在很多情况下,我们会遇到依赖的依赖,即间接依赖。例如amin的依赖文件roscpp也有其他依赖。如果我们使用rospack depends amin,则会列出amin功能包的所有依赖文件。

第二步:声明可执行文件

接下来,我们需要在 CMakeLists.txt 中添加两行,来声明我们需要创建的可执行文件。其一般形式是:

add_executable(executable-name source-files)
target_link_libraries(executable-name ${catkin_LIBRARIES})
  • 第一行声明了我们想要的可执行文件的文件名,以及生成此可执行文件所需的源文件列表。如果你有多个源文件,把它们列在此处,并用空格将其区分开。
  • 第二行告诉 Cmake 当链接此可执行文件时需要链接哪些库(在上面的 find_package 中定义)。如果你的包中包括多个可执行文件,为每一个可执行文件复制和修改上述两行代码。

在本例程中,我们需要一个名为 hello 的可执行文件,它通过名为 hello.cpp 的源文件编译而来。所以我们需要添加如下两行代码到 CMakeLists.txt 文件中 include_directories(include ${catkin_INCLUDE_DIRS}) 之后:

add_executable(hello hello.cpp)
target_link_libraries(hello ${catkin_LIBRARIES})

第三步:编译工作区

利用catkin_make这个命令进行编译,注意必须在你的工作空间目录运行。

cd ~/dev/catkin_ws
catkin_make

运行完后会在 ~/dev/catkin_ws/devel/amin 目录下生产 hello 这个可执行文件。下图为运行的结果。

五、执行hello程序

首先要启动 roscore:这个程序是一个节点,节点需要一个节点管理器才可以正常运行。启动节点管理器的命令:

roscore

启动完节点管理器后,执行名为 setup.bash 的脚本文件,它是 catkin_make 在你工作区的 devel 子目录下生成的。这个自动生成的脚本文件设置了若干环境变量,从而使 ROS 能够找到你创建的功能包和新生成的可执行文件。(也就是将程序注册)

source devel/setup.bash

最后一步,运行节点,用命令:使用格式为"rosrun package-name executable-name" ,package-name 为功能包名称, executable-name为可执行文件名称。

rosrun amin hello

运行结果如图:

这样一个简单的ROS程序就完成了。

ROS学习笔记三:编写第一个ROS节点程序的更多相关文章

  1. Android:日常学习笔记(2)——分析第一个Android应用程序

    Android:日常学习笔记(2)——分析第一个Android应用程序 Android项目结构 整体目录结构分析 说明: 除了APP目录外,其他目录都是自动生成的.APP目录的下的内容才是我们的工作重 ...

  2. ROS学习笔记三(理解ROS节点)

    要求已经在Linux系统中安装一个学习用的ros软件包例子: sudo apt-get install ros-indigo-ros-tutorials ROS图形概念概述 nodes:节点,一个节点 ...

  3. Apache Ignite 学习笔记(三): Ignite Server和Client节点介绍

    在前两篇文章中,我们把Ignite集群当做一个黑盒子,用二进制包自带的脚本启动Ignite节点后,我们用不同的客户端连接上Ignite进行操作,展示了Ignite作为一个分布式内存缓存,内存数据库的基 ...

  4. ROS学习笔记(三)

    机器人建模与仿真URDF(Unified Robot Descrption Format,统一机器人描述格式),ROS提供了URDF的c++解析器.安装语法检查工具sudo apt-get insta ...

  5. Ajax学习笔记1之第一个Ajax应用程序

    代码 <head> <title>An Ajax demo</title> <script src="../js/jquery-1.4.1.js&q ...

  6. ROS学习手记 - 8 编写ROS的Publisher and Subscriber

    上一节我们完成了 message & srv 文件的创建和加入编译,这次我们要玩简单的Publisher 和 Subscriber 要玩 Publisher 和 Subscriber, 需要具 ...

  7. Learning ROS for Robotics Programming Second Edition学习笔记(三) 补充 hector_slam

    中文译著已经出版,详情请参考:http://blog.csdn.net/ZhangRelay/article/category/6506865 Learning ROS for Robotics Pr ...

  8. Learning ROS for Robotics Programming Second Edition学习笔记(三) indigo rplidar rviz slam

    中文译著已经出版,详情请参考:http://blog.csdn.net/ZhangRelay/article/category/6506865 Learning ROS for Robotics Pr ...

  9. ROS学习笔记七:在ROS中使用USB摄像头

    下面是一些USB摄像头的驱动(大多数摄像头都支持uvc标准): 1 使用软件库里的uvc-camera功能包 1.1 检查摄像头 lsusb ----------------------------- ...

随机推荐

  1. 下一代的中间件必须是支持docker规范的

    下一代的中间件必须是支持docker规范的,这是中间件技术走向标准规范化的必经之路. 什么是 Docker? 答案是:Docker 是下一代的云计算模式.Docker 是下一代云计算的主流趋势. Do ...

  2. Linux驱动开发:USB驱动之usb_skel分析

    在学习了这么些天的驱动之后,个人觉得驱动就是个架构的问题,只要把架构弄清楚了 然后往里面添砖加瓦就可以了,所以似乎看起来不是太困难,但也许是是我经验不足吧,这只能算是个人浅见了 这两天在学习USB驱动 ...

  3. 理解Paxos Made Practical

    Paxos Made Practical 当一个组中一台机器提出一个值时,其它成员机器通过PAXOS算法在这个值上达成一致. Paxos分三个阶段. 第一阶段: 提出者会选出一个提议编号n(n> ...

  4. Cts框架解析(6)-任务的运行

    前两篇讲了任务的加入和9大项配置,这篇讲任务的运行. 任务的运行 任务的运行在CommandScheduler的run方法中,所以删除全部的断点,在run方法中打上断点,重新启动启动debug: 先看 ...

  5. Java对象的创建过程

    //TODO https://www.cnblogs.com/chenyangyao/p/5296807.html

  6. ffmpeg+libx264+facc交叉编译 实现264流录制avi文件

    默认交叉编译器已经搭建好. .. . . . . .... .... 需求: 把标准的h264流保存成avi格式的实现文件,所以须要h264的解码器,avi文件容器,传输协议类型是文件.这些会体如今f ...

  7. 02-Swift学习笔记-元组类型

    02-Swift学习笔记-元组类型 元组类型由N个任意类型的数据组成(N>=0) 元组类型的数据称为"元素" eg var size = (x:100 , y:100) si ...

  8. Eclipse项目遇到问题汇总

    1:gc overhead limit exceeded     原因:这是由于项目中eclipse内存分配不足导致     修改:修改eclipse.ini文件     修改如下:          ...

  9. Java基础学习之final和多态及类型转换

    finalkeyword: finalkeyword是终于的意思,能够修饰类,成员变量,成员方法. •    修饰类,类不能被继承 •    修饰变量,变量就变成了常量,仅仅能被赋值一次. •    ...

  10. HDU 5544 Ba Gua Zhen dfs+高斯消元

    Ba Gua Zhen Problem Description During the Three-Kingdom period, there was a general named Xun Lu wh ...