02.ROS 空间、文件系统以及小乌龟

安装好了ROS过后就可以开始下面ROS的工作环境了

主要参考下面文档:CSDN ROS入门教程(一)

一、ROS的工作环境

1.1 管理ROS环境

确保ROS的环境变量已经被设置

# bash 中输入下面的信息,会输出一大串关于ROS的环境信息
printenv | grep ROS

1.2 创建ROS工作空间

ROS Groovy发布于2012年,在这版本以及之后的都使用catkin进行创建ROS工作空间的工作。

mkdir -p ~/catkin_ws/src
cd ~/catkin_ws/
catkin_make

在工作空间首次运行 catkin_make 命令后,它会在 ./src 目录下创建一个 CMakeLists.txt 文件。

jet@jet-vm:~/catkin_ws$ ls
# 输出如下
build devel src

devel 文件夹中会有几个 setup.sh* 文件。source 命令执行其中的文件会覆盖工作空间顶层的环境。

source devel/setup.bash   
# 因为我这里使用的是默认的bash环境,如果是zsh则是另外一个

查看是否修改了环境变量:

$echo $ROS_PACKAGE_PATH

jet@jet-vm:~/catkin_ws$ printenv | grep ROS

通过对比输出可以发现环境变量中 ROS_PACKAGE_PATHROSLISP_PACKAGE_DIRECTORIES 发生了变化。

二、ROS文件系统

因为一开始安装ROS的时候选项是 ros-kinetic-desktop-full 所以下面需要的文件系统已经安装完毕了。

2.1 文件系统的概念

  • Packages:Packages是ROS代码的软件单元的一种组织方式,每个Package可以包含库,可执行程序,脚本等。

  • Manifests(Package.xml):manifest是一个package的描述文件,它定义了包之间的依赖,并用来捕获包的元信息(meta information,元数据是关于数据的组织、数据域及其关系的信息,简言之,元数据就是关于数据的数据。),例如版本,维护者,证书等等。

2.3 文件系统工具

ROS代码有独有的包管理命令

  • rospack = ros+package

    rospack 可以获取有关packages的信息,帮助命令是 rospack help

    jet@jet-vm:~/catkin_ws$ rospack find roscpp
    # 会输出相关信息
    
  • roscd = ros+cd

    roscd 是 rosbash 的一部分,此命令可以切换到包的相关目录中。

    jet@jet-vm:~/catkin_ws$ roscd roscpp
    jet@jet-vm:~/catkin_ws$ pwd
    

    注:ROS工具只寻找 ROS_PACKAGE_PATH 所列出路径,其中的每个路径用 ”:“ 进行分隔。

  • roscd log

    此命令会进入ROS的log文件夹,如果之前没有运行过ROS程序则会报错。

  • rosls = ros+ls

ROS工具中很多都是 ROS+XX组合的命令。

三、创建ROS Package

此章节使用 roscreate-pkgcatkin 创建一个新的package,并用rospack列出包的依赖关系。

3.1 一个catkin package的组成

  • 必须包含一个catkin兼容的package.xml文件

  • 必须包含一个使用catkin的CMakeLists.txt

  • 每个package必须有自己的文件夹:这意味着没有嵌套的包,也没有共享同一目录的多个包。

    最简单的package如下:

    my_package/
        CMakeLists.txt
        package.xml
    

3.2 catkin工作空间中的package

使用catkin packages工作的推荐方式的是使用catkin工作空间,当然也可以单独建立一个catkin package。一个普通的工作空间大概如下:

jet@jet-vm:~/catkin_ws$ tree
.
├── build
│   ├── atomic_configure
│   │   ├── env.sh
│   │   ├── local_setup.bash
│   │   ├── local_setup.sh
│   │   ├── local_setup.zsh
│   │   ├── setup.bash
│   │   ├── setup.sh
│   │   ├── _setup_util.py
│   │   └── setup.zsh
│   ├── catkin
│   │   └── catkin_generated
│   │       └── version
│   │           └── package.cmake
│   ├── catkin_generated
│   │   ├── env_cached.sh
│   │   ├── generate_cached_setup.py
│   │   ├── installspace
│   │   │   ├── env.sh
│   │   │   ├── local_setup.bash
│   │   │   ├── local_setup.sh
│   │   │   ├── local_setup.zsh
│   │   │   ├── setup.bash
│   │   │   ├── setup.sh
│   │   │   ├── _setup_util.py
│   │   │   └── setup.zsh
│   │   ├── order_packages.cmake
│   │   ├── order_packages.py
│   │   ├── setup_cached.sh
│   │   └── stamps
│   │       └── Project
│   │           ├── interrogate_setup_dot_py.py.stamp
│   │           ├── order_packages.cmake.em.stamp
│   │           ├── package.xml.stamp
│   │           └── _setup_util.py.stamp
│   ├── CATKIN_IGNORE
│   ├── catkin_make.cache
│   ├── CMakeCache.txt
│   ├── CMakeFiles
│   │   ├── 3.5.1
│   │   │   ├── CMakeCCompiler.cmake
│   │   │   ├── CMakeCXXCompiler.cmake
│   │   │   ├── CMakeDetermineCompilerABI_C.bin
│   │   │   ├── CMakeDetermineCompilerABI_CXX.bin
│   │   │   ├── CMakeSystem.cmake
│   │   │   ├── CompilerIdC
│   │   │   │   ├── a.out
│   │   │   │   └── CMakeCCompilerId.c
│   │   │   └── CompilerIdCXX
│   │   │       ├── a.out
│   │   │       └── CMakeCXXCompilerId.cpp
│   │   ├── clean_test_results.dir
│   │   │   ├── build.make
│   │   │   ├── cmake_clean.cmake
│   │   │   ├── DependInfo.cmake
│   │   │   └── progress.make
│   │   ├── cmake.check_cache
│   │   ├── CMakeDirectoryInformation.cmake
│   │   ├── CMakeError.log
│   │   ├── CMakeOutput.log
│   │   ├── CMakeRuleHashes.txt
│   │   ├── CMakeTmp
│   │   ├── download_extra_data.dir
│   │   │   ├── build.make
│   │   │   ├── cmake_clean.cmake
│   │   │   ├── DependInfo.cmake
│   │   │   └── progress.make
│   │   ├── doxygen.dir
│   │   │   ├── build.make
│   │   │   ├── cmake_clean.cmake
│   │   │   ├── DependInfo.cmake
│   │   │   └── progress.make
│   │   ├── feature_tests.bin
│   │   ├── feature_tests.c
│   │   ├── feature_tests.cxx
│   │   ├── Makefile2
│   │   ├── Makefile.cmake
│   │   ├── progress.marks
│   │   ├── run_tests.dir
│   │   │   ├── build.make
│   │   │   ├── cmake_clean.cmake
│   │   │   ├── DependInfo.cmake
│   │   │   └── progress.make
│   │   ├── TargetDirectories.txt
│   │   └── tests.dir
│   │       ├── build.make
│   │       ├── cmake_clean.cmake
│   │       ├── DependInfo.cmake
│   │       └── progress.make
│   ├── cmake_install.cmake
│   ├── CTestConfiguration.ini
│   ├── CTestCustom.cmake
│   ├── CTestTestfile.cmake
│   ├── gtest
│   │   ├── CMakeFiles
│   │   │   ├── CMakeDirectoryInformation.cmake
│   │   │   ├── gmock.dir
│   │   │   │   ├── build.make
│   │   │   │   ├── cmake_clean.cmake
│   │   │   │   ├── DependInfo.cmake
│   │   │   │   ├── depend.make
│   │   │   │   ├── flags.make
│   │   │   │   ├── link.txt
│   │   │   │   ├── progress.make
│   │   │   │   ├── src
│   │   │   │   └── usr
│   │   │   │       └── src
│   │   │   │           └── gtest
│   │   │   │               └── src
│   │   │   ├── gmock_main.dir
│   │   │   │   ├── build.make
│   │   │   │   ├── cmake_clean.cmake
│   │   │   │   ├── DependInfo.cmake
│   │   │   │   ├── depend.make
│   │   │   │   ├── flags.make
│   │   │   │   ├── link.txt
│   │   │   │   ├── progress.make
│   │   │   │   ├── src
│   │   │   │   └── usr
│   │   │   │       └── src
│   │   │   │           └── gtest
│   │   │   │               └── src
│   │   │   └── progress.marks
│   │   ├── cmake_install.cmake
│   │   ├── CTestTestfile.cmake
│   │   ├── gtest
│   │   │   ├── CMakeFiles
│   │   │   │   ├── CMakeDirectoryInformation.cmake
│   │   │   │   ├── gtest.dir
│   │   │   │   │   ├── build.make
│   │   │   │   │   ├── cmake_clean.cmake
│   │   │   │   │   ├── DependInfo.cmake
│   │   │   │   │   ├── depend.make
│   │   │   │   │   ├── flags.make
│   │   │   │   │   ├── link.txt
│   │   │   │   │   ├── progress.make
│   │   │   │   │   └── src
│   │   │   │   ├── gtest_main.dir
│   │   │   │   │   ├── build.make
│   │   │   │   │   ├── cmake_clean.cmake
│   │   │   │   │   ├── DependInfo.cmake
│   │   │   │   │   ├── depend.make
│   │   │   │   │   ├── flags.make
│   │   │   │   │   ├── link.txt
│   │   │   │   │   ├── progress.make
│   │   │   │   │   └── src
│   │   │   │   └── progress.marks
│   │   │   ├── cmake_install.cmake
│   │   │   ├── CTestTestfile.cmake
│   │   │   └── Makefile
│   │   └── Makefile
│   ├── Makefile
│   └── test_results
├── devel
│   ├── cmake.lock
│   ├── env.sh
│   ├── lib
│   ├── local_setup.bash
│   ├── local_setup.sh
│   ├── local_setup.zsh
│   ├── setup.bash
│   ├── setup.sh
│   ├── _setup_util.py
│   └── setup.zsh
└── src
    └── CMakeLists.txt -> /opt/ros/kinetic/share/catkin/cmake/toplevel.cmake

43 directories, 123 files
jet@jet-vm:~/catkin_ws$ 

3.3 创建一个catkin Package

  • 创建工作空间的方法在章节:1.2 创建ROS的工作环境

  • 创建package代码:

    # 示例
    catkin_create_pkg <package_name> [depend1][depend2][depend3]
    #具体命令
    $ cd ~/catkin_ws/src
    
    jet@jet-vm:~/catkin_ws/src$ catkin_create_pkg beginner_tutorials std_msgs rospy roscpp
    Created file beginner_tutorials/package.xml
    Created file beginner_tutorials/CMakeLists.txt
    Created folder beginner_tutorials/include/beginner_tutorials
    Created folder beginner_tutorials/src
    Successfully created files in /home/jet/catkin_ws/src/beginner_tutorials. Please adjust the values in package.xml.
    jet@jet-vm:~/catkin_ws/src$ 
    

3.4 编译catkin工作空间并source

//主要命令如下
$ cd ~/catkin_ws
$ catkin_make 
$ . ~/catkin_ws/devel/setup.bash
jet@jet-vm:~/catkin_ws/src$ cd ..
jet@jet-vm:~/catkin_ws$ catkin_make
Base path: /home/jet/catkin_ws
Source space: /home/jet/catkin_ws/src
Build space: /home/jet/catkin_ws/build
Devel space: /home/jet/catkin_ws/devel
Install space: /home/jet/catkin_ws/install
####
#### Running command: "cmake /home/jet/catkin_ws/src -DCATKIN_DEVEL_PREFIX=/home/jet/catkin_ws/devel -DCMAKE_INSTALL_PREFIX=/home/jet/catkin_ws/install -G Unix Makefiles" in "/home/jet/catkin_ws/build"
####
-- Using CATKIN_DEVEL_PREFIX: /home/jet/catkin_ws/devel
-- Using CMAKE_PREFIX_PATH: /opt/ros/kinetic
-- This workspace overlays: /opt/ros/kinetic
-- Using PYTHON_EXECUTABLE: /usr/bin/python
-- Using Debian Python package layout
-- Using empy: /usr/bin/empy
-- Using CATKIN_ENABLE_TESTING: ON
-- Call enable_testing()
-- Using CATKIN_TEST_RESULTS_DIR: /home/jet/catkin_ws/build/test_results
-- Found gmock sources under '/usr/src/gmock': gmock will be built
-- Found gtest sources under '/usr/src/gmock': gtests will be built
-- Using Python nosetests: /usr/bin/nosetests-2.7
-- catkin 0.7.18
-- BUILD_SHARED_LIBS is on
-- BUILD_SHARED_LIBS is on
-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-- ~~  traversing 1 packages in topological order:
-- ~~  - beginner_tutorials
-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-- +++ processing catkin package: 'beginner_tutorials'
-- ==> add_subdirectory(beginner_tutorials)
-- Configuring done
-- Generating done
-- Build files have been written to: /home/jet/catkin_ws/build
####
#### Running command: "make -j2 -l2" in "/home/jet/catkin_ws/build"
####
jet@jet-vm:~/catkin_ws$ . ~/catkin_ws/devel/setup.bash 
jet@jet-vm:~/catkin_ws$ 

3.5 package依赖

  • 一级依赖

    jet@jet-vm:~/catkin_ws$ rospack depends1 beginner_tutorials 
    roscpp
    rospy
    std_msgs
    jet@jet-vm:~/catkin_ws$ 
    # 此命令的输出与创建package时传入的参数一致,这些对packages的依赖存储在package.xml 中
    
  • 间接依赖

    jet@jet-vm:~/catkin_ws$ rospack depends1 rospy
    genpy
    roscpp
    rosgraph
    rosgraph_msgs
    roslib
    std_msgs
    jet@jet-vm:~/catkin_ws$ 
    #一般情况下,一个依赖项目都有自己的依赖项,rospack可以递归检测所有的嵌套依赖。
    

3.6 定制package

  • 定制package.xml

    包括description,maintainer,lincense,dependencies(包括了 buildtool_depend,build_depend,exec_depend)

  • 定制CMakeLists.txt

四、编译Package

4.1 编译package

  • catkin_make 可以看做是标准的cmake工作流程:cmake,make

    # In a CMake Project
    $ mkdir build
    $ cd build
    $ cmake ..
    $ make 
    $ make install  #(optionally)
    # In a catkin workspace
    $ catkin_make
    $ catkin_make install #(optionally)
    

    catkin_make 命令将编译 src 目录下的所有工程。对于源码不再当前目录下的使用方法为:

    # In a catkin workspace
    $ catkin_make --source my_src
    $ catkin_make install --source my_src #(optionally)
    
  • 编译package

    在当前工作空间中(~/catkin_ws): catkin_make

五、ROS Nodes

本节引入ROS Graph的概念,并探讨roscore,rosnode,rosrun的使用。

5.1 Graph的概念

  • Nodes:一个node表示一个使用ROS来与其他nodes进行通讯的可执行程序。

  • Messages:ROS的数据类型

  • Topics:Nodes可以向topic发布消息,也可以订阅topic来接收消息。

  • Master:Name sevice for ROS(帮助节点找到彼此)

  • rosout:ROS下的stdout/stderr。

  • roscore:Master + rosout + parameter server

5.2 Nodes

在ROS package中,一个Node实际上只不过是一个可执行文件。ROS Nodes使用ROS client library与其他nodes进行通信。Nodes可以发布和订阅一个Topic。Nodes也可以提供或使用一个sevice。

5.3 Client Libraries

ROS client library 允许使用不同编程语言写出来的Nodes进行通信。

  • rospy = python client library

  • roscpp = C plus plus client library

5.4 roscore

roscore 是当你使用ROS时第一个应该运行的核心程序。

5.5 使用rosnode

rosnode显示当前正在运行的有关ROS nodes的信息

# 列出活跃状态的nodes
jet@jet-vm:~$ rosnode list
/rosout
jet@jet-vm:~$ rosnode info /rosout
--------------------------------------------------------------------------------
Node [/rosout]
Publications: 
 * /rosout_agg [rosgraph_msgs/Log]

Subscriptions: 
 * /rosout [unknown type]

Services: 
 * /rosout/get_loggers
 * /rosout/set_logger_level


contacting node http://jet-vm:41897/ ...
Pid: 2381

jet@jet-vm:~$ 

5.6 使用rosrun

rosrun 允许使用package名来直接运行一个package中的node(不必知道package的路径)。

# usage : rosrun [package_name] [nodename]
jet@jet-vm:~$ rosrun turtlesim turtlesim_node
[ INFO] [1565093878.731080946]: Starting turtlesim with node name /turtlesim
[ INFO] [1565093878.747198414]: Spawning turtle [turtle1] at x=[5.544445], y=[5.544445], theta=[0.000000]
# 弹出一个乌龟的窗口

ROS支持为node重新指定名字

$ rosrun turtlesim turtlesim_node __name:=my_turtle
jet@jet-vm: ~ $ rosnode list
/my_turtle
/rosout

可以使用 rosnode 的 ping 参数来测试是否node正常运行。

jet@jet-vm:~$ rosnode ping turtlesim
rosnode: node is [/turtlesim]
pinging /turtlesim with a timeout of 3.0s
xmlrpc reply from http://jet-vm:36863/  time=0.334024ms
xmlrpc reply from http://jet-vm:36863/  time=2.504826ms
xmlrpc reply from http://jet-vm:36863/  time=1.864910ms
xmlrpc reply from http://jet-vm:36863/  time=1.274824ms
xmlrpc reply from http://jet-vm:36863/  time=1.255035ms
^Cping average: 1.446724ms
jet@jet-vm:~$ 

如果出现上面的输出代表已经成功运行了。

5.7 总结

  • roscore 是所有运行的核心 = ros + core: master(prodives name service for ROS) + rosout(stdout/stderr) +parameter server.

  • rosnode = ros + node : ROS tool to get Information about a node.

  • rosrun = ros + run: runs a node from a given package

六、ROS Topics

本节引入ROS topics,与此同时使用rostopic和rqt_plot工具

6.1 准备工作

  • 确保roscore在运行,在一个新打开的终端输入roscore可进行测试。

  • 运行如下命令

    $ rosrun turtlesim turtlesim_node
    
  • 运行如下命令

    $ rosrun turtlesim turtle_teleop_key
    # 之后可以使用方向按键控制乌龟动起来了
    

6.2 ROS Topics

  • 使用 rqt-graph

    rqt-graph 创建系统的一个动态范围。rqt-graphrqt package 的一部分,安装方法如下:

    # 按照正常安装全部的方法都是已经安装好了
    $ sudo apt-get install ros-kinetic-rqt
    $ sudo apt-get install ros-kinetic-rqt-common-plugins
    

    在终端中输入以下命令会出现一个可视化窗口显示nodes之间的关系。

    $ rosrun rqt_graph rqt_graph
    
  • 引入 rostopic

    rostopic 工具用来获取 ROS topics。

  • 使用 rostopic echo

    rostopic echo 显示发布在一个topic上的数据,只有在运行之后有新的消息发布到topic上时才会有输出

    # Usage
    $ rostopic echo [topic]
    $ rostopic echo /turtle1/cmd_vel
    
  • 使用**rostopic list **

    使用 $ rostopic list -v 列出所有的 topics

    jet@jet-vm:~$ rostopic list -v
    
    Published topics:
     * /turtle1/color_sensor [turtlesim/Color] 1 publisher
     * /turtle1/cmd_vel [geometry_msgs/Twist] 1 publisher
     * /rosout [rosgraph_msgs/Log] 3 publishers
     * /rosout_agg [rosgraph_msgs/Log] 1 publisher
     * /turtle1/pose [turtlesim/Pose] 1 publisher
    
    Subscribed topics:
     * /turtle1/cmd_vel [geometry_msgs/Twist] 2 subscribers
     * /rosout [rosgraph_msgs/Log] 1 subscriber
    
    jet@jet-vm:~$ 
    

6.3 ROS Messages

ropics上的通讯是通过在nodes之间发送 ROS messages进行的。发布者和订阅者必须发哦是那个和接收同种类型的消息。这意味着,topic的类型是由发布在其上的message类型定义的。message的类型可通过 rostopic type [topic] 来查询。可以使用 rosmsg show type 查看信息格式。

jet@jet-vm:~$ rostopic list -v

Published topics:
 * /turtle1/color_sensor [turtlesim/Color] 1 publisher
 * /turtle1/cmd_vel [geometry_msgs/Twist] 1 publisher
 * /rosout [rosgraph_msgs/Log] 3 publishers
 * /rosout_agg [rosgraph_msgs/Log] 1 publisher
 * /turtle1/pose [turtlesim/Pose] 1 publisher

Subscribed topics:
 * /turtle1/cmd_vel [geometry_msgs/Twist] 2 subscribers
 * /rosout [rosgraph_msgs/Log] 1 subscriber

jet@jet-vm:~$ rostopic type /turtle1/cmd_vel
geometry_msgs/Twist
jet@jet-vm:~$ rosmsg show geometry_msgs/Twist
geometry_msgs/Vector3 linear
  float64 x
  float64 y
  float64 z
geometry_msgs/Vector3 angular
  float64 x
  float64 y
  float64 z

jet@jet-vm:~$ 

6.4 rostopic 续

  • rostopic pub可以在一个topic上发布数据

    # Usage: rostopic pub [topic] [msg_type] [args]
    # 双短线表示后边的不是命令选项而是参数
    jet@jet-vm:~$ rostopic pub -l /turtle1/cmd_vel geometry_msgs/Twist -- '[2.0,0.0,0.0]' '[0.0,0.0,1.0]'
    publishing and latching message. Press ctrl-C to terminate
    
    # 此时可以看到乌龟动了,几次执行下来可以看到乌龟走了一个纯圆。
    
1565098084483.png
  • rostopic hz 报告数据发布速率: $ rostopic hz [topic]
jet@jet-vm:~$ rostopic hz /turtle1/cmd_vel 
subscribed to [/turtle1/cmd_vel]
no new messages
no new messages
average rate: 4.828
    min: 0.144s max: 0.288s std dev: 0.04833s window: 6
average rate: 5.999
    min: 0.099s max: 0.288s std dev: 0.04975s window: 13
average rate: 7.209
    min: 0.042s max: 0.298s std dev: 0.06797s window: 23

当有数据变动的时候也就是有数据传输。

6.5 使用 rqt_plot

使用指令 $ rosrun rqt_plot rqt_plot ,添加需要查看的topic。

七、ROS Services and Parameters

本节介绍ROS Services and Parameters,与此同时使用使用 rosservicerosparam 命令行工具。services 是nodes间进行通信的另一种方式,services 允许nodes发送一个请求(request)和接收一个响应(response)。

#Usage:
$ rosservice list [topic] #列出[topic]锁提供的服务
$ rosservice type [service] # 显示服务类型
$ rosservice call [service] [args] # 调用服务

# 查看带参数的示例
rosservice find #find service by service type
rosservice uri  #print service ROSRPC uri
jet@jet-vm:~/work$ rosservice type /spawn | rossrv show
float32 x
float32 y
float32 theta
string name
---
string name

jet@jet-vm:~/work$ rosservice call /spawn 2 2 0.2 "" # name field is optional
name: "turtle2"

rosparam 循序我们存储和操作 ROS parameter Server 上的数据,Parameter Server

可以存储整型,浮点型,布尔型,字典,列表。rosparam 使用 YAML 标记语言语法。

#Usage: 
rosparam set [param_name] #set parameter
# 设置参数过后使用 /clear 服务刷新操作
$ rosservice call /clear
rosparam get [param_name] # get parameter
rosparam load # load parameter from file
rosparam dump # dump parameters to file
rosparam delete # delete parameter
rosparam list # list parameter names
# Usage
rosparam dump [file_name] [namespace]
rosparam load [file_name] [namespace]
# write all the parameters to the file params.yaml
$ rosparam dump params.yaml
# load these yaml files into new namespaces, e.g. copy
$ rosparam load params.yaml copy
$ rosparam get /copy/background_b

推荐阅读更多精彩内容