ros 学习记录

2 篇文章 0 订阅

#1. Installing and Configuring Your ROS Environment
rosws
rosws is part of the rosinstall package. See py-rosws-stacks.]
##Managing Your Environment
在安装过程中ROS的,你会看到提示您激活几个设setup.*sh文件,甚至将这种“激活”添加到你的shell启动脚本。这是必需的,因为ROS依赖于使用shell环境组合空间的概念。这使得针对不同版本的ROS或针对不同的包集合进行开发更容易。

如果您在查找或使用ROS软件包时遇到问题,请确保正确设置环境。检查的一个好方法是确保设置ROS_ROOTROS_PACKAGE_PATH环境变量

$ printenv | grep ROS

ROS_ROOT sets the location where the ROS core packages are installed.

export ROS_ROOT=/home/user/ros/ros
export PATH=$ROS_ROOT/bin:$PATH

ROS_PACKAGE_PATH是一个可选但非常常见的环境变量,允许您从源向环境添加更多ROS包。ROS_PACKAGE_PATH可以由一个或多个由标准OS路径分隔符分隔的路径组成(例如,类Unix系统上的’:’)。这些有序路径告诉ROS系统在哪里搜索更多ROS包。如果有相同名称的多个包,ROS会选择上出现的一个ROS_PACKAGE_PATH 第一。

export ROS_PACKAGE_PATH = / home / user / ros / ros-pkg:/ another / path

请注意,ROS_PACKAGE_PATH中的每个条目都是递归搜索的 - 将找到命名路径下的所有ROS包。
随着catkin的引入,ROS_PACKAGE_PATH变得过时,并且仅为了向后兼容rosbuild包而保留。

If you just installed ROS from apt on Ubuntu then you will have setup.*sh files in/opt/ros/<distro>/, and you could source them like so:

$ source /opt/ros/<distro>/setup.bash

Using the short name of your ROS distribution instead of <distro>
If you installed ROS Kinetic, that would be:

$ source /opt/ros/kinetic/setup.bash

You will need to run this command on every new shell you open to have access to the ROS commands, unless you add this line to your .bashrc. This process allows you to install several ROS distributions (e.g. indigo and kinetic) on the same computer and switch between them.
##Create a ROS Workspace
Let’s create and build a catkin workspace:

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

在“devel”文件夹中,您可以看到现在有几个setup。* sh文件。获取这些文件中的任何一个都会将此工作区覆盖在您的环境之上
source your new setup.*sh file:

$ source devel / setup.bash

要确保设置脚本正确覆盖您的工作区,请确保ROS_PACKAGE_PATH环境变量包含您所在的目录。

$ echo $ROS_PACKAGE_PATH
/home/youruser/catkin_ws/src:/opt/ros/kinetic/share

Catkin Workspaces

catkin包可以构建为独立项目,与构建普通cmake项目的方式相同,但catkin还提供了工作空间的概念,您可以在其中同时构建多个相互依赖的包。
一个catkin工作区最多可包含四个不同的空间,每个服务在软件开发过程中不同的角色。
source space build space development space install space
result space(either be a development space or an install space)
Overlays(覆盖)

Environment Setup File

二进制catkin包中包含一组用于扩展shell环境的环境设置文件,以便您可以查找和使用已安装到本地的任何资源。
you must source the setup file included in the root of the distribution install directory (usually /opt/ros/<ros_distribution_name>)

/
  opt/
    ros/
      kinetic/
        setup.bash -- Environment setup file for Bash shell
        setup.sh   -- Environment setup file for Bourne shell
        setup.zsh  -- Environment setup file for zshell
        ...

To setup your environment to use the /opt/ros/kinetic installation space, source the setup file for your shell:

source /opt/ros/kinetic/setup.bash

2.Navigating the ROS Filesystem

##Prerequisites

$ sudo apt-get install ros-<distro>-ros-tutorials

Replace '<distro>' (including the '<>') with the name of your ROS distribution (e.g. indigo, kinetic, lunar etc.)
###Filesystem Tools
代码分布在许多ROS包中。使用命令行工具(如ls和cd)进行导航可能非常繁琐,这也是ROS提供工具来帮助您的原因。
####使用rospack
rospack允许您获取有关包的信息。在本教程中,我们将仅介绍find选项,它返回package的路径
用法:

$ rospack find [package_name]

例如:

$  rospack find roscpp
/opt/ros/kinetic/share/roscpp

####Using roscd
roscd is part of the rosbash suite. It allows you to change directory (cd) directly to a package or a stack.
例如:

qy@QY:~/catkin_ws2$ roscd roscpp
qy@QY:/opt/ros/kinetic/share/roscpp$ 

Now let’s print the working directory using the Unix command pwd:

qy@QY:/opt/ros/kinetic/share/roscpp$ pwd
/opt/ros/kinetic/share/roscpp

Note that roscd, like other ROS tools, will only find ROS packages that are within the directories listed in your ROS_PACKAGE_PATH. To see what is in your ROS_PACKAGE_PATH, type:

$ echo $ROS_PACKAGE_PATH

例如:

$ echo $ROS_PACKAGE_PATH
/home/qy/catkin_ws2/src:/opt/ros/kinetic/share

Similarly to other environment paths, you can add additional directories to your ROS_PACKAGE_PATH, with each path separated by a colon ‘:’
Subdirectories
roscd can also move to a subdirectory of a package or stack.
Try:

$ roscd roscpp/cmake
$ pwd

/opt/ros/kinetic/share/roscpp/cmake
roscd log
roscd log will take you to the folder where ROS stores log files

$ roscd log

Using rosls
rosls is part of the rosbash suite. It allows you to ls directly in a package by name rather than by absolute path.
Usage:

$ rosls [locationname[/subdir]]

例如:

$ rosls roscpp_tutorials

would return:

cmake launch package.xml  srv

###Tab Completion(标签完成)
It can get tedious(繁琐的) to type out an entire package name. In the previous example, roscpp_tutorials is a fairly(十分) long name. Luckily, some ROS tools support TAB completion.
#3.Creating a ROS Package
说明:本教程介绍使用roscreate-PKG或cakin创建一个新包,rospack列出软件包的依赖。
###3.1. What makes up a catkin Package?
对于一个catkin package 必须要满足一下几个要求:

  • 包必须包含一个catkin conplicant package.xml 文件
  • 包必须包含一个CMakeLists.txt(使用catkin)
  • 每个包必须有自己的文件夹
    最简单的形式如下:
my_package/
  CMakeLists.txt
  package.xml

#3.2 Packages in a catkin Workspace
推荐使用catkin workspace来管理catkin packages,但是你也可以单独地建立catkin packages.一个常见的空间是下面这个样子:

workspace_folder/        -- WORKSPACE
  src/                   -- SOURCE SPACE
    CMakeLists.txt       -- 'Toplevel' CMake file, provided by catkin
    package_1/
      CMakeLists.txt     -- CMakeLists.txt file for package_1
      package.xml        -- Package manifest for package_1
    ...
    package_n/
      CMakeLists.txt     -- CMakeLists.txt file for package_n
      package.xml        -- Package manifest for package_n

3…3 Creating a catkin Package
如何使用catkin_create_pkg脚本创建一个新的catkin package

# You should have created this in the Creating a Workspace Tutorial
$ cd ~/catkin_ws/src

使用 catkin_create_pkg 脚本来创建一个名为beginner_tutorials(依赖于std_msgs roscpp和rospy

$ catkin_create_pkg beginner_tutorials std_msgs rospy roscpp

这会创建一个beginner_tutorials 文件夹,它包含了package.xml和CMakeLists.txt,其中一些内容是通过 给 catkin_create_pkg 的信息来填入的.
catkin_create_pkg requires that you give it a package_name and optionally a list of dependencies on which that package depends:

# This is an example, do not try to run this
# catkin_create_pkg <package_name> [depend1] [depend2] [depend3]

###3.4.Building a catkin workspace and sourcing the setup file

$ cd ~/catkin_ws
$ catkin_make

After the workspace has been built it has created a similar structure in the devel subfolder as you usually find under /opt/ros/$ROSDISTRO_NAME.
To add the workspace to your ROS environment you need to source the generated setup file:

$ . ~/catkin_ws/devel/setup.bash

###3.5 package dependencies
First-order dependencies(一阶依赖)
When using catkin_create_pkg earlier, a few package dependencies were provided. These first-order dependencies can now be reviewed with the rospack tool.

$ rospack depends1 beginner_tutorials 

结果:

roscpp
rospy
std_msgs

These dependencies for a package are stored in the package.xml file:

$ roscd beginner_tutorials
$ cat package.xml
<package format="2">
...
  <buildtool_depend>catkin</buildtool_depend>
  <build_depend>roscpp</build_depend>
  <build_depend>rospy</build_depend>
  <build_depend>std_msgs</build_depend>
...
</package>

Indirect dependencies
In many cases, a dependency will also have its own dependencies. For instance, rospy has other dependencies.

$ rospack depends1 rospy
genpy
roscpp
rosgraph
rosgraph_msgs
roslib
std_msgs

A package can have quite a few indirect dependencies. Luckily rospack can recursively determine all nested dependencies.

$ rospack depends beginner_tutorials

###3.6Customizing Your Package
3.6.1Customizing the package.xml
description tag

   5   <description>The beginner_tutorials package</description>

描述用一行话,否则会出错.
maintainer tags

   7   <!-- One maintainer tag required, multiple allowed, one person per tag --> 
   8   <!-- Example:  -->
   9   <!-- <maintainer email="jane.doe@example.com">Jane Doe</maintainer> -->
  10   <maintainer email="user@todo.todo">user</maintainer>

The name of the maintainer goes into the body of the tag, but there is also an email attribute that should be filled out.
license tags

  12   <!-- One license tag required, multiple allowed, one license per tag -->
  13   <!-- Commonly used license strings: -->
  14   <!--   BSD, MIT, Boost Software License, GPLv2, GPLv3, LGPLv2.1, LGPLv3 -->
  15   <license>TODO</license>

For this tutorial we’ll use the BSD license because the rest of the core ROS components use it already:

   8   <license>BSD</license>

dependencies tags
The dependencies are split into build_depend, buildtool_depend, exec_depend, test_depend.
Since we passed std_msgs, roscpp, and rospy as arguments to catkin_create_pkg, the dependencies will look like this:

  27   <!-- The *_depend tags are used to specify dependencies -->
  28   <!-- Dependencies can be catkin packages or system dependencies -->
  29   <!-- Examples: -->
  30   <!-- Use build_depend for packages you need at compile time: -->
  31   <!--   <build_depend>genmsg</build_depend> -->
  32   <!-- Use buildtool_depend for build tool packages: -->
  33   <!--   <buildtool_depend>catkin</buildtool_depend> -->
  34   <!-- Use exec_depend for packages you need at runtime: -->
  35   <!--   <exec_depend>python-yaml</exec_depend> -->
  36   <!-- Use test_depend for packages you need only for testing: -->
  37   <!--   <test_depend>gtest</test_depend> -->
  38   <buildtool_depend>catkin</buildtool_depend>
  39   <build_depend>roscpp</build_depend>
  40   <build_depend>rospy</build_depend>
  41   <build_depend>std_msgs</build_depend>

In this case we want all of our specified dependencies to be available at build and run time, so we’ll add a exec_depend tag for each of them as well:

  12   <buildtool_depend>catkin</buildtool_depend>
  13 
  14   <build_depend>roscpp</build_depend>
  15   <build_depend>rospy</build_depend>
  16   <build_depend>std_msgs</build_depend>
  17 
  18   <exec_depend>roscpp</exec_depend>
  19   <exec_depend>rospy</exec_depend>
  20   <exec_depend>std_msgs</exec_depend>

Final package.xml
As you can see the final package.xml, without comments and unused tags, is much more concise:

   1 <?xml version="1.0"?>
   2 <package format="2">
   3   <name>beginner_tutorials</name>
   4   <version>0.1.0</version>
   5   <description>The beginner_tutorials package</description>
   6 
   7   <maintainer email="you@yourdomain.tld">Your Name</maintainer>
   8   <license>BSD</license>
   9   <url type="website">http://wiki.ros.org/beginner_tutorials</url>
  10   <author email="you@yourdomain.tld">Jane Doe</author>
  11 
  12   <buildtool_depend>catkin</buildtool_depend>
  13 
  14   <build_depend>roscpp</build_depend>
  15   <build_depend>rospy</build_depend>
  16   <build_depend>std_msgs</build_depend>
  17 
  18   <exec_depend>roscpp</exec_depend>
  19   <exec_depend>rospy</exec_depend>
  20   <exec_depend>std_msgs</exec_depend>
  21 
  22 </package>

3.6.2 Customizing the CMakeLists.txt
The CMakeLists.txt file created by catkin_create_pkg will be covered in the later tutorials about building ROS code.
#4.Building a ROS Package
###4.1Building Packages

$ source /opt/ros/kinetic/setup.bash             # For Kinetic for instance

Using catkin_make
可以想象catkin_make将调用cmake和make组合在标准CMake工作流中。

# In a catkin workspace
$ catkin_make [make_targets] [-DCMAKE_VARIABLES=...]

CMake workflow, it breaks down as follows:

# In a CMake project
$ mkdir build
$ cd build
$ cmake ..
$ make
$ make install  # (optionally)

Building zero to many catkin packages in a workspace follows this work flow:

# In a catkin workspace
$ catkin_make
$ catkin_make install  # (optionally)

If your source code is in a different place, say my_src then you would call catkin_make like this:

# In a catkin workspace
$ catkin_make --source my_src
$ catkin_make install --source my_src  # (optionally)

###4.2Building Your Package

$ cd ~/catkin_ws/
$ ls src

We can now build that package using catkin_make:

$ catkin_make

The build folder is the default location of the build space and is where cmake and make are called to configure and build your packages. The devel folder is the default location of the devel space, which is where your executables and libraries go before you install your packages.
#5 Understanding ROS Nodes
Description: This tutorial introduces ROS graph concepts and discusses the use of roscore, rosnode, and rosrun commandline tools
###Quick Overview of Graph Concepts:

  • Nodes: A node is an executable that uses ROS to communicate with
    other nodes.
  • Messages: ROS data type used when subscribing or publishing to a topic.
  • Topics: Nodes can publish messages to a topic as well as subscribe to a topic to receive messages.
  • Master:节点管理器,ros名称服务,(比如帮组节点找到彼此) Name service for ROS (i.e. helps nodes find each other)
  • rosout: ROS equivalent of stdout/stderr
  • roscore: Master + rosout + parameter server (parameter server will be introduced later)
    ###Nodes
    节点实际上只不过是ROS包中的可执行文件。ROS节点使用ROS客户端库与其他节点通信。节点可以发布或订阅主题。节点还可以提供或使用服务。
    ###Client Libraries (客户端库)

rospy = python client library
roscpp = c++ client library
###roscore
roscore is the first thing you should run when using ROS.

$ roscore

###Using rosnode
Bare in mind to keep the previous terminal open either by opening a new tab or simply minimizing it.

$ rosnode list

You will see:
/rosout
This is always running as it collects and logs nodes’ debugging output.
The rosnode info command returns information about a specific node.

$ rosnode info /rosout

###Using rosrun
rosrun allows you to use the package name to directly run a node within a package (without having to know the package path).

$ rosrun [package_name] [node_name]

so:

$ rosrun turtlesim turtlesim_node

In a new terminal:

$ rosnode list

You will see something similar to:

/rosout
/turtlesim

One powerful feature of ROS is that you can reassign Names from the command-line.

$ rosrun turtlesim turtlesim_node __name:=my_turtle
$ rosnode list

will see:

/my_turtle
/rosout

Note: If you still see/turtlesim in the list, it might mean that you stopped the node in the terminal using ctrl-C instead of closing the window, or that you don’t have the $ROS_HOSTNAME environment variable defined as described in Network Setup - Single Machine Configuration. You can try cleaning the rosnode list with: $ rosnode cleanup
We see our new /my_turtle node. Let’s use another rosnode command, ping, to test that it’s up(测试是否工作):

$ rosnode ping my_turtle

###Review
What was covered:
roscore = ros+core : master (provides name service for ROS) + rosout (stdout/stderr) + parameter server (parameter server will be introduced later)
rosnode = ros+node : ROS tool to get information about a node.
rosrun = ros+run : runs a node from a given package.
#6 Understanding ROS Topics
Setup
Let’s start by making sure that we have roscore running, in a new terminal:

$ roscore

turtlesim:

$ rosrun turtlesim turtlesim_node

turtle keyboard teleoperation

$ rosrun turtlesim turtle_teleop_key

ROS Topics
Using rqt_graph

$ rosrun rqt_graph rqt_graph

Introducing rostopic

$ rostopic -h

rostopic bw     display bandwidth used by topic
rostopic echo   print messages to screen
rostopic hz     display publishing rate of topic    
rostopic list   print information about active topics
rostopic pub    publish data to topic
rostopic type   print topic type

Using rostopic echo

rostopic echo [topic]
$ rostopic echo /turtle1/cmd_vel

Using rostopic list
For rostopic list use the verbose option:

$ rostopic list -v

ROS Messages
通过在节点之间发送ROS 消息来进行主题通信。对于要发布的发布者(turtle_teleop_key)和订阅者(turtlesim_node),发布者和订阅者必须发送和接收相同类型的消息。This means that a topic type is defined by the message type published on it. The type of the message sent on a topic can be determined using rostopic type.
Using rostopic type

rostopic type [topic]
$ rostopic type /turtle1/cmd_vel

得到:
geometry_msgs/Twist
We can look at the details of the message using rosmsg:

$ rosmsg show geometry_msgs/Twist

rostopic continued
Using rostopic pub
rostopic pub publishes data on to a topic currently advertised.
Usage:

rostopic pub [topic] [msg_type] [args]
$ rostopic pub -1 /turtle1/cmd_vel geometry_msgs/Twist -- '[2.0, 0.0, 0.0]' '[0.0, 0.0, 1.8]'

这里写图片描述
explain:
This command will publish messages to a given topic:

rostopic pub

This option (dash-one) causes rostopic to only publish one message then exit:

 -1 

This is the name of the topic to publish to:

/turtle1/cmd_vel

This is the message type to use when publishing to the topic:

geometry_msgs/Twist

his option (double-dash) tells the option parser that none of the following arguments is an option. This is required in cases where your arguments have a leading dash -, like negative numbers.
As noted before, a geometry_msgs/Twist msg has two vectors of three floating point elements each: linear and angular. In this case, ‘[2.0, 0.0, 0.0]’ becomes the linear value with x=2.0, y=0.0, and z=0.0, and ‘[0.0, 0.0, 1.8]’ is the angular value with x=0.0, y=0.0, and z=1.8. These arguments are actually in YAML syntax, which is described more in the YAML command line documentation.

'[2.0, 0.0, 0.0]' '[0.0, 0.0, 1.8]' 

You may have noticed that the turtle has stopped moving; this is because the turtle requires a steady stream of commands at 1 Hz to keep moving. We can publish a steady stream of commands using rostopic pub -r command:

$ rostopic pub /turtle1/cmd_vel geometry_msgs/Twist -r 1 -- '[2.0, 0.0, 0.0]' '[0.0, 0.0, -1.8]'

这里写图片描述
Using rostopic hz
rostopic hz reports the rate at which data is published.
Usage:

rostopic hz [topic]

Let’s see how fast the turtlesim_node is publishing /turtle1/pose:

$ rostopic hz /turtle1/pose
$ rostopic type /turtle1/cmd_vel | rosmsg show

Using rqt_plot

$ rosrun rqt_plot rqt_plot

in a new terminal. In the new window that should pop up, a text box in the upper left corner gives you the ability to add any topic to the plot. Typing/turtle1/pose/x will highlight the plus button, previously disabled. Press it and repeat the same procedure with the topic /turtle1/pose/y. You will now see the turtle’s x-y location plotted in the graph.
这里写图片描述
#7.Understanding ROS Services and Parameters
Description: This tutorial introduces ROS services, and parameters as well as using the rosservice and rosparam commandline tools.
目录
ROS Services
Using rosservice
rosservice list
rosservice type
rosservice call
Using rosparam
rosparam list
rosparam set and rosparam get
rosparam dump and rosparam load

Assuming your turtlesim_node is still running from the last tutorial, let’s look at what services the turtlesim provides:
ROS Services
Services are another way that nodes can communicate with each other. Services allow nodes to send a request and receive a response.
Using rosservice
rosservice可以把services轻松附加到ROS的客户端/服务框架。rosservice有许多可用于主题的命令,如下所示:

用法:

rosservice list         print information about active services
rosservice call         call the service with the provided args
rosservice type         print service type
rosservice find         find services by service type
rosservice uri          print service ROSRPC uri

rosservice list

$ rosservice list

The list command shows us that the turtlesim node provides nine services
rosservice type

rosservice type [service]

Let’s find out what type the clear service is:

$ rosservice type /clear

结果:
std_srvs/Empty
This service is empty, this means when the service call is made it takes no arguments
rosservice call
用法:

rosservice call [service] [args]

Here we’ll call with no arguments because the service is of type empty:

$ rosservice call /clear

This does what we expect, it clears the background of the turtlesim_node.

Let’s look at the case where the service has arguments by looking at the information for the service spawn:

$ rosservice type /spawn | rossrv show

结果:

float32 x
float32 y
float32 theta
string name
---
string name

这项服务让我们在给定的位置和方向产生一只新的乌龟。name字段是可选的,所以我们不要给我们的新龟命名,让turtlesim为我们创建一个。

$ rosservice call / spawn 2 2 0.2“”

使用rosparam
rosparam allows you to store and manipulate data on the ROS Parameter Server,rosparam uses the YAML markup language for syntax.
用法:

rosparam set            set parameter
rosparam get            get parameter
rosparam load           load parameters from file
rosparam dump           dump parameters to file
rosparam delete         delete parameter
rosparam list           list parameter names

rosparam list
Let’s look at what parameters are currently on the param server:

$ rosparam list

rosparam set and rosparam get
用法:

rosparam set [param_name]
rosparam get [param_name]

Here will change the red channel of the background color:

$ rosparam set /background_r 150

Now let’s look at the values of other parameters on the param server. Let’s get the value of the green background channel:

$ rosparam get /background_g

结果:
86
We can also use rosparam get / to show us the contents of the entire Parameter Server.

$ rosparam get /

结果:

background_b: 255
background_g: 86
background_r: 150
roslaunch:
  uris: {'aqy:51932': 'http://aqy:51932/'}
run_id: e07ea71e-98df-11de-8875-001b21201aa8

rosparam dump and rosparam load

用法:

rosparam dump [file_name] [namespace]
rosparam load [file_name] [namespace]

Here we write all the parameters to the file params.yaml

$ rosparam dump params.yaml

这里的文件好像保存到当前文件夹
You can even load these yaml files into new namespaces, e.g. copy:

$ rosparam load params.yaml copy
$ rosparam get /copy/background_b

结果:
255
#8.Using rqt_console and roslaunch
说明:本教程使用ROS介绍rqt_console和rqt_logger_level用于调试以及使用roslaunch在一次启动多个节点
Prerequisites rqt and turtlesim package

$ sudo apt-get install ros-<distro>-rqt ros-<distro>-rqt-common-plugins ros-<distro>-turtlesim

Replace <distro> with the name of your ROS distribution (e.g. indigo, jade, kinetic, lunar…).
Using rqt_console and rqt_logger_level
rqt_console attaches to ROS’s logging framework to display output from nodes. rqt_logger_level allows us to change the verbosity level (DEBUG, WARN, INFO, and ERROR) of nodes as they run.

$ rosrun rqt_console rqt_console
$ rosrun rqt_logger_level rqt_logger_level

Now let’s start turtlesim in a new terminal:

$ rosrun turtlesim turtlesim_node

Quick Note about logger levels

Fatal
Error
Warn
Info
Debug

Using roslaunch
roslaunch starts nodes as defined in a launch file.
用法:

$ roslaunch [package] [filename.launch]
$ cd ~/catkin_ws
$ source devel/setup.bash
$ roscd beginner_tutorials

Then let’s make a launch directory:

$ mkdir launch
$ cd launch

注意:存储启动文件的目录不一定必须命名为launch。实际上,您甚至不需要将它们存储在目录中。roslaunch命令自动查看传递的包并检测可用的启动文件。但是,这被认为是一种很好的做法。
The Launch File

切换行号显示
<launch>

  <group ns="turtlesim1">
    <node pkg="turtlesim" name="sim" type="turtlesim_node"/>
  </group>

  <group ns="turtlesim2">
    <node pkg="turtlesim" name="sim" type="turtlesim_node"/>
  </group>

  <node pkg="turtlesim" name="mimic" type="mimic">
    <remap from="input" to="turtlesim1/turtle1"/>
    <remap from="output" to="turtlesim2/turtle1"/>
  </node>

</launch>

roslaunching
Now let’s roslaunch the launch file:

$ roslaunch beginner_tutorials turtlemimic.launch
$ rostopic pub /turtlesim1/turtle1/cmd_vel geometry_msgs/Twist -r 1 -- '[2.0, 0.0, 0.0]' '[0.0, 0.0, -1.8]'

You will see the two turtlesims start moving even though the publish command is only being sent to turtlesim1.
这里写图片描述
#9.Using rosed to edit files in ROS
Using rosed
用法:

$ rosed [package_name] [filename]

例如:

$ rosed roscpp Logger.msg

Using rosed with tab completion
用法:

$ rosed [package_name] <tab><tab>

例如:

$ rosed roscpp <tab><tab>
Empty.srv                   package.xml
GetLoggers.srv              roscpp-msg-extras.cmake
Logger.msg                  roscpp-msg-paths.cmake
SetLoggerLevel.srv          roscpp.cmake
genmsg_cpp.py               roscppConfig-version.cmake
gensrv_cpp.py               roscppConfig.cmake
msg_gen.py

Editor
The default editor for rosed is vim. The more beginner-friendly editor nano is included with the default Ubuntu install. You can use it by editing your ~/.bashrcfile to include:

export EDITOR='nano -w'

Open a new terminal and see if EDITOR is defined:

$ echo $EDITOR

结果:
nano -w

#10.Creating a ROS msg and srv
本节主要讲述了如何创建和建立ROS msg和srv,同时使用命令行工具rosmsg、rossrv和roscp。
Introduction to msg and srv

  • msg: msg files are simple text files that describe the fields of a
    ROS message. They are used to generate source code for messages in
    different languages.
  • srv: an srv file describes a service. It is composed of two parts: a request and a response.
    msg文件存放在一个软件包的msg目录中,而srv文件则存放在srv目录中来。
    msg文件就是一个简单的text文件,其中每行有一个类型和名称,可用的类型如下:
int8, int16, int32, int64 (plus uint*)
float32, float64
string
time, duration
other msg files
variable-length array[] and fixed-length array[C]

Here is an example of a msg that uses a Header, a string primitive, and two other msgs :

  Header header
  string child_frame_id
  geometry_msgs/PoseWithCovariance pose
  geometry_msgs/TwistWithCovariance twist

srv files are just like msg files, except they contain two parts: a request and a response. The two parts are separated by a ‘—’ line. Here is an example of a srv file:

int64 A
int64 B
---
int64 Sum

In the above example, A and B are the request, and Sum is the response.
Using msg
Creating a msg
Let’s define a new msg in the package that was created in the previous tutorial.

$ roscd beginner_tutorials
$ mkdir msg
$ echo "int64 num" > msg/Num.msg

不过还有一个步骤。我们需要确保将msg文件转换为C ++,Python和其他语言的源代码:
打开package.xml,确保这两行都在其中并取消注释

  <build_depend> message_generation </ build_depend>
  <exec_depend> message_runtime </ exec_depend>

at build time, we need "message_generation", while at runtime, we only need "message_runtime".
Open CMakeLists.txt in your favorite text editor (rosed from the previous tutorial is a good option).
在 CMakeLists.txt文件中,利用find_packag函数,增加对message_generation的依赖,这样就可以生成消息了。 你可以直接在COMPONENTS的列表里增加message_generation,就像这样:

# Do not just add this to your CMakeLists.txt, modify the existing text to add message_generation before the closing parenthesis
find_package(catkin REQUIRED COMPONENTS
   roscpp
   rospy
   std_msgs
   message_generation
)

有时候你会发现,即使你没有调用find_package,你也可以编译通过。这是因为catkin把你所有的package都整合在一起,因此,如果其他的package调用了find_package,你的package的依赖就会是同样的配置。但是,在你单独编译时,忘记调用find_package会很容易出错。
Also make sure you export the message runtime dependency.

catkin_package(
  ...
  CATKIN_DEPENDS message_runtime ...
  ...)

Find the following block of code:

# add_message_files(
#   FILES
#   Message1.msg
#   Message2.msg
# )

Uncomment it by removing the # symbols and then replace the stand in Message*.msg files with your .msg file, such that it looks like this:

add_message_files(
  FILES
  Num.msg
)

By adding the .msg files manually, we make sure that CMake knows when it has to reconfigure the project after you add other .msg files.
Now we must ensure the generate_messages() function is called.

# generate_messages(
#   DEPENDENCIES
#   std_msgs
# )

so it looks like:

		generate_messages(
		  DEPENDENCIES
		  std_msgs
		)

Using rosmsg
That’s all you need to do to create a msg. Let’s make sure that ROS can see it using the rosmsg show command.
用法:

$ rosmsg show [message type]

例如:

$ rosmsg show beginner_tutorials/Num

int64 num

In the previous example, the message type consists of two parts:

  • beginner_tutorials – the package where the message is defined
  • Num – The name of the msg Num.

If you can’t remember which Package a msg is in, you can leave out the package name. Try:

$ rosmsg show Num

You will see:

[beginner_tutorials/Num]:
int64 num

Using srv
Creating a srv
Let’s use the package we just created to create a srv:

$ roscd beginner_tutorials
$ mkdir srv

Instead of creating a new srv definition by hand, we will copy an existing one from another package.
For that, roscp is a useful commandline tool for copying files from one package to another.
用法:

$ roscp [package_name] [file_to_copy_path] [copy_path]

Now we can copy a service from the rospy_tutorials package:

$ roscp rospy_tutorials AddTwoInts.srv srv/AddTwoInts.srv

There’s one more step, though. We need to make sure that the srv files are turned into source code for C++, Python, and other languages.
Unless you have done so already, open package.xml, and make sure these two lines are in it and uncommented:

  <build_depend>message_generation</build_depend>
  <exec_depend>message_runtime</exec_depend>

As before, note that at build time, we need “message_generation”, while at runtime, we only need “message_runtime”.

Unless you have done so already for messages in the previous step, add the message_generation dependency to generate messages in CMakeLists.txt:

# Do not just add this line to your CMakeLists.txt, modify the existing line
find_package(catkin REQUIRED COMPONENTS
  roscpp
  rospy
  std_msgs
  message_generation
)

(Despite its name, message_generation works for both msg and srv.)
Also you need the same changes to package.xml for services as for messages, so look above for the additional dependencies required.
Remove # to uncomment the following lines:

# add_service_files(
#   FILES
#   Service1.srv
#   Service2.srv
# )

Using rossrv
That’s all you need to do to create a srv. Let’s make sure that ROS can see it using therossrv show command.
用法:

$ rossrv show <service type>

例如:

$ rossrv show beginner_tutorials/AddTwoInts

You will see:

int64 a
int64 b
---
int64 sum

Similar to rosmsg, you can find service files like this without specifying package name:

$ rossrv show AddTwoInts
[beginner_tutorials/AddTwoInts]:
int64 a
int64 b
---
int64 sum

[rospy_tutorials/AddTwoInts]:
int64 a
int64 b
---
int64 sum

Common step for msg and srv
Unless you have already done this in the previous steps, change in CMakeLists.txt. :

# generate_messages(
#   DEPENDENCIES
# #  std_msgs  # Or other packages containing msgs
# )

Uncomment it and add any packages you depend on which contain .msg files that your messages use (in this case std_msgs), such that it looks like this:

generate_messages(
  DEPENDENCIES
  std_msgs
)

Now that we have made some new messages we need to make our package again:

# In your catkin workspace
$ roscd beginner_tutorials
$ cd ../..
$ catkin_make install
$ cd -

Any .msg file in the msg directory will generate code for use in all supported languages. The C++ message header file will be generated in
~/catkin_ws/devel/include/beginner_tutorials/.
The Python script will be created in
~/catkin_ws/devel/lib/python2.7/dist-packages/beginner_tutorials/msg.
The lisp file appears in~/catkin_ws/devel/share/common-lisp/ros/beginner_tutorials/msg/.
Similarly, any .srv files in the srv directory will have generated code in supported languages. For C++, this will generate header files in the same directory as the message header files. For Python and Lisp, there will be an ‘srv’ folder beside the ‘msg’ folders.
If you are building C++ nodes which use your new messages, you will also need to declare a dependency between your node and your message, as described in the catkin msg/srv build documentation.
Getting Help
We’ve seen quite a few ROS tools already. It can be difficult to keep track of what arguments each command requires. Luckily, most ROS tools provide their own help.
$ rosmsg -h
You should see a list of different rosmsg subcommands

Commands:
  rosmsg show     Show message description
  rosmsg list     List all messages
  rosmsg md5      Display message md5sum
  rosmsg package  List messages in a package
  rosmsg packages List packages that contain messages

You can also get help for subcommands

$ rosmsg show -h

This shows the arguments that are needed for rosmsg show:

Usage: rosmsg show [options] <message type>

Options:
  -h, --help  show this help message and exit
  -r, --raw   show raw message text, including comments

Review
Let’s just list some of the commands we’ve used so far:

  • rospack = ros+pack(age) : provides information related to ROS packages
  • roscd = ros+cd : changes directory to a ROS package or stack
  • rosls = ros+ls : lists files in a ROS package
  • roscp = ros+cp : copies files from/to a ROS package
  • rosmsg = ros+msg : provides information related to ROS message definitions
  • rossrv = ros+srv : provides information related to ROS service definitions
  • catkin_make : makes (compiles) a ROS package
  • rosmake = ros+make : makes (compiles) a ROS package (if you’re not using a catkin workspace)

11.writing a simple publisher and subscriber(c++)

Writing the Publisher Node
“Node” is the ROS term for an executable that is connected to the ROS network. Here we’ll create a publisher (“talker”) node which will continually broadcast a message.

roscd beginner_tutorials

The Code
Create a src directory in the beginner_tutorials package directory:

mkdir -p src

This directory will contain any source files for our beginner_tutorials package.
Create the src/talker.cpp file within the beginner_tutorials package and paste the following inside it:

#include "ros/ros.h"
#include "std_msgs/String.h"

#include <sstream>

/**
 * This tutorial demonstrates simple sending of messages over the ROS system.
 */
int main(int argc, char **argv)
{
  /**
   * The ros::init() function needs to see argc and argv so that it can perform
   * any ROS arguments and name remapping that were provided at the command line.
   * For programmatic remappings you can use a different version of init() which takes
   * remappings directly, but for most command-line programs, passing argc and argv is
   * the easiest way to do it.  The third argument to init() is the name of the node.
   *
   * You must call one of the versions of ros::init() before using any other
   * part of the ROS system.
   */
  ros::init(argc, argv, "talker");

  /**
   * NodeHandle is the main access point to communications with the ROS system.
   * The first NodeHandle constructed will fully initialize this node, and the last
   * NodeHandle destructed will close down the node.
   */
  ros::NodeHandle n;

  /**
   * The advertise() function is how you tell ROS that you want to
   * publish on a given topic name. This invokes a call to the ROS
   * master node, which keeps a registry of who is publishing and who
   * is subscribing. After this advertise() call is made, the master
   * node will notify anyone who is trying to subscribe to this topic name,
   * and they will in turn negotiate a peer-to-peer connection with this
   * node.  advertise() returns a Publisher object which allows you to
   * publish messages on that topic through a call to publish().  Once
   * all copies of the returned Publisher object are destroyed, the topic
   * will be automatically unadvertised.
   *
   * The second parameter to advertise() is the size of the message queue
   * used for publishing messages.  If messages are published more quickly
   * than we can send them, the number here specifies how many messages to
   * buffer up before throwing some away.
   */
  ros::Publisher chatter_pub = n.advertise<std_msgs::String>("chatter", 1000);

  ros::Rate loop_rate(10);

  /**
   * A count of how many messages we have sent. This is used to create
   * a unique string for each message.
   */
  int count = 0;
  while (ros::ok())
  {
    /**
     * This is a message object. You stuff it with data, and then publish it.
     */
    std_msgs::String msg;

    std::stringstream ss;
    ss << "hello world " << count;
    msg.data = ss.str();

    ROS_INFO("%s", msg.data.c_str());

    /**
     * The publish() function is how you send messages. The parameter
     * is the message object. The type of this object must agree with the type
     * given as a template parameter to the advertise<>() call, as was done
     * in the constructor above.
     */
    chatter_pub.publish(msg);

    ros::spinOnce();

    loop_rate.sleep();
    ++count;
  }


  return 0;
}

The Code Explained
Now, let’s break the code down.(代码分析)

#include "ros/ros.h"

ros/ros.h is a convenience include that includes all the headers necessary to use the most common public pieces of the ROS system.

#include "std_msgs/String.h"

This includes the std_msgs/String message, which resides in the std_msgs package. This is a header generated automatically from the String.msg file in that package. For more information on message definitions, see the msg page.

ros::init(argc, argv, "talker");

Initialize ROS. This allows ROS to do name remapping through the command line – not important for now. This is also wspecify the name of our node. Node names must be unique in a running system.

ros::NodeHandle n;

Create a handle to this process’ node. The first NodeHandle created will actually do the initialization of the node, and the last one destructed will cleanup any resources the node was using.

 ros::Publisher chatter_pub = n.advertise<std_msgs::String>("chatter", 1000);

Tell the master that we are going to be publishing a message of type std_msgs/String on the topic chatter. This lets the master tell any nodes listening on chatter that we are going to publish data on that topic. The second argument is the size of our publishing queue. In this case if we are publishing too quickly it will buffer up a maximum of 1000 messages before beginning to throw away old ones.
NodeHandle::advertise()returns a ros::Publisher object, which serves two purposes: 1) it contains a publish() method that lets you publish messages onto the topic it was created with, and 2) when it goes out of scope, it will automatically unadvertise.

ros::Rate loop_rate(10);

A ros::Rate object allows you to specify a frequency that you would like to loop at. It will keep track of how long it has been since the last call to Rate::sleep(), and sleep for the correct amount of time.
In this case we tell it we want to run at 10Hz.

  int count = 0;
  while (ros::ok())
  {

By default roscpp will install a SIGINT handler which provides Ctrl-Chandling which will cause ros::ok()to return false if that happens.
ros::ok() will return false if:

  • a SIGINT is received(收到) (Ctrl-C)
  • we have been kicked off the network by another node with the same name
  • ros::shutdown() has been called by another part of the application.
  • all ros::NodeHandles have been destroyed
    Once ros::ok()returns false, all ROS calls will fail.
    std_msgs::String msg;

    std::stringstream ss;
    ss << "hello world " << count;
    msg.data = ss.str();

We broadcast a message on ROS using a message-adapted class, generally generated from a msg file. More complicated datatypes are possible, but for now we’re going to use the standard String message, which has one member: “data”.

chatter_pub.publish(msg);

Now we actually broadcast the message to anyone who is connected.

ROS_INFO("%s", msg.data.c_str());

ROS_INFO and friends are our replacement for printf/cout. See the rosconsole documentation for more information.

ros::spinOnce();

Calling ros::spinOnce() here is not necessary for this simple program, because we are not receiving any callbacks. However, if you were to add a subscription into this application, and did not have ros::spinOnce() here, your callbacks would never get called. So, add it for good measure.

loop_rate.sleep();

Now we use the ros::Rate object to sleep for the time remaining to let us hit our 10Hz publish rate.
Here’s the condensed version(简缩) of what’s going on:(总结)

  • Initialize the ROS system
  • Advertise that we are going to be publishing std_msgs/String messages on the chatter topic to the master
  • Loop while publishing messages to chatter 10 times a second
    Writing the Subscriber Node
    The Code
    Create the src/listener.cpp file within the beginner_tutorials package and paste the following inside it:
#include "ros/ros.h"
#include "std_msgs/String.h"

/**
 * This tutorial demonstrates simple receipt of messages over the ROS system.
 */
void chatterCallback(const std_msgs::String::ConstPtr& msg)
{
  ROS_INFO("I heard: [%s]", msg->data.c_str());
}

int main(int argc, char **argv)
{
  /**
   * The ros::init() function needs to see argc and argv so that it can perform
   * any ROS arguments and name remapping that were provided at the command line.
   * For programmatic remappings you can use a different version of init() which takes
   * remappings directly, but for most command-line programs, passing argc and argv is
   * the easiest way to do it.  The third argument to init() is the name of the node.
   *
   * You must call one of the versions of ros::init() before using any other
   * part of the ROS system.
   */
  ros::init(argc, argv, "listener");

  /**
   * NodeHandle is the main access point to communications with the ROS system.
   * The first NodeHandle constructed will fully initialize this node, and the last
   * NodeHandle destructed will close down the node.
   */
  ros::NodeHandle n;

  /**
   * The subscribe() call is how you tell ROS that you want to receive messages
   * on a given topic.  This invokes a call to the ROS
   * master node, which keeps a registry of who is publishing and who
   * is subscribing.  Messages are passed to a callback function, here
   * called chatterCallback.  subscribe() returns a Subscriber object that you
   * must hold on to until you want to unsubscribe.  When all copies of the Subscriber
   * object go out of scope, this callback will automatically be unsubscribed from
   * this topic.
   *
   * The second parameter to the subscribe() function is the size of the message
   * queue.  If messages are arriving faster than they are being processed, this
   * is the number of messages that will be buffered up before beginning to throw
   * away the oldest ones.
   */
  ros::Subscriber sub = n.subscribe("chatter", 1000, chatterCallback);

  /**
   * ros::spin() will enter a loop, pumping callbacks.  With this version, all
   * callbacks will be called from within this thread (the main one).  ros::spin()
   * will exit when Ctrl-C is pressed, or the node is shutdown by the master.
   */
  ros::spin();

  return 0;
}

The Code Explained
Now, let’s break it down piece by piece, ignoring some pieces that have already been explained above.

void chatterCallback(const std_msgs::String::ConstPtr& msg)
{
  ROS_INFO("I heard: [%s]", msg->data.c_str());
}

This is the callback function that will get called when a new message has arrived on the chatter topic. The message is passed in a boost shared_ptr, which means you can store it off if you want, without worrying about it getting deleted underneath you, and without copying the underlying data.

ros::Subscriber sub = n.subscribe("chatter", 1000, chatterCallback);

Subscribe to the chatter topic with the master. ROS will call the chatterCallback() function whenever a new message arrives. The 2nd argument is the queue size, in case we are not able to process messages fast enough. In this case, if the queue reaches 1000 messages, we will start throwing away old messages as new ones arrive.
NodeHandle::subscribe() returns a ros::Subscriber object, that you must hold on to until you want to unsubscribe. When the Subscriber object is destructed, it will automatically unsubscribe from the chatter topic.
There are versions of the NodeHandle::subscribe() function which allow you to specify a class member function, or even anything callable by a Boost.Function object. The roscpp overview contains more information.

ros::spin();

ros::spin()enters a loop, calling message callbacks as fast as possible. Don’t worry though, if there’s nothing for it to do it won’t use much CPU. ros::spin() will exit once ros::ok() returns false, which means ros::shutdown() has been called, either by the default Ctrl-C handler, the master telling us to shutdown, or it being called manually.
There are other ways of pumping callbacks, but we won’t worry about those here. The roscpp_tutorials package has some demo applications which demonstrate this. The roscpp overview also contains more information.
Again, here’s a condensed version of what’s going on:
Initialize the ROS system
Subscribe to the chatter topic
Spin, waiting for messages to arrive
When a message arrives, the chatterCallback() function is called
Building your nodes
You used catkin_create_pkgin a previous tutorial which created a package.xml and a CMakeLists.txt file for you.
The generated CMakeLists.txt should look like this (with modifications from the Creating Msgs and Srvs tutorial and unused comments and examples removed):

cmake_minimum_required(VERSION 2.8.3)
project(beginner_tutorials)

## Find catkin and any catkin packages
find_package(catkin REQUIRED COMPONENTS roscpp rospy std_msgs genmsg)

## Declare ROS messages and services
add_message_files(DIRECTORY msg FILES Num.msg)
add_service_files(DIRECTORY srv FILES AddTwoInts.srv)

## Generate added messages and services
generate_messages(DEPENDENCIES std_msgs)

## Declare a catkin package
catkin_package()

Don’t worry about modifying the commented (#) examples, simply add these few lines to the bottom of your CMakeLists.txt:

add_executable(talker src/talker.cpp)
target_link_libraries(talker ${catkin_LIBRARIES})
add_dependencies(talker beginner_tutorials_generate_messages_cpp)

add_executable(listener src/listener.cpp)
target_link_libraries(listener ${catkin_LIBRARIES})
add_dependencies(listener beginner_tutorials_generate_messages_cpp)

Your resulting CMakeLists.txt file should look like this:

cmake_minimum_required(VERSION 2.8.3)
project(beginner_tutorials)

## Find catkin and any catkin packages
find_package(catkin REQUIRED COMPONENTS roscpp rospy std_msgs genmsg)

## Declare ROS messages and services
add_message_files(FILES Num.msg)
add_service_files(FILES AddTwoInts.srv)

## Generate added messages and services
generate_messages(DEPENDENCIES std_msgs)

## Declare a catkin package
catkin_package()

## Build talker and listener
include_directories(include ${catkin_INCLUDE_DIRS})

add_executable(talker src/talker.cpp)
target_link_libraries(talker ${catkin_LIBRARIES})
add_dependencies(talker beginner_tutorials_generate_messages_cpp)

add_executable(listener src/listener.cpp)
target_link_libraries(listener ${catkin_LIBRARIES})
add_dependencies(listener beginner_tutorials_generate_messages_cpp)

This will create two executables, talker and listener, which by default will go into package directory of your devel space, located by default at ~/catkin_ws/devel/lib/<package name>
Note that you have to add dependencies for the executable targets to message generation targets:

add_dependencies(talker beginner_tutorials_generate_messages_cpp)

This makes sure message headers of this package are generated before being used. If you use messages from other packages inside your catkin workspace, you need to add dependencies to their respective generation targets as well, because catkin builds all projects in parallel. As of Groovy you can use the following variable to depend on all necessary targets:

target_link_libraries(talker ${catkin_LIBRARIES})

You can invoke executables directly or you can use rosrun to invoke them. They are not placed in ‘< prefix >/bin’ because that would pollute the PATH when installing your package to the system. If you wish for your executable to be on the PATH at installation time, you can setup an install target, see: catkin/CMakeLists.txt
For more detailed discription of the CMakeLists.txt file see: catkin/CMakeLists.txt
Now run catkin_make:

# In your catkin workspace
$ cd ~/catkin_ws
$ catkin_make  

Note: Or if you’re adding as new pkg, you may need to tell catkin to force making by --force-cmake option. See catkin/Tutorials/using_a_workspace#With_catkin_make.

Now that you have written a simple publisher and subscriber, let’s examine the simple publisher and subscriber.

14.Writing a Simple Service and Client (C++)

Description: This tutorial covers how to write a service and client node in C++
##1.Writing a Service Node
Here we’ll create the service (“add_two_ints_server”) node which will receive two ints and return the sum.
Change directories to your beginner_tutorials package you created in your catkin workspace previous tutorials:

roscd beginner_tutorials

Please make sure you have followed the directions in the previous tutorial for creating the service needed in this tutorial, creating the AddTwoInts.srv (be sure to choose the right version of build tool you’re using at the top of wiki page in the link).
1.1The Code
Create the src/add_two_ints_server.cpp file within the beginner_tutorials package and paste the following inside it:

#include "ros/ros.h"
#include "beginner_tutorials/AddTwoInts.h"

bool add(beginner_tutorials::AddTwoInts::Request  &req,
         beginner_tutorials::AddTwoInts::Response &res)
{
  res.sum = req.a + req.b;
  ROS_INFO("request: x=%ld, y=%ld", (long int)req.a, (long int)req.b);
  ROS_INFO("sending back response: [%ld]", (long int)res.sum);
  return true;
}

int main(int argc, char **argv)
{
  ros::init(argc, argv, "add_two_ints_server");
  ros::NodeHandle n;

  ros::ServiceServer service = n.advertiseService("add_two_ints", add);
  ROS_INFO("Ready to add two ints.");
  ros::spin();

  return 0;
}

1.2 The Code Explained
Now, let’s break the code down.

#include "ros/ros.h"
#include "beginner_tutorials/AddTwoInts.h"

beginner_tutorials/AddTwoInts.h is the header file generated from the srv file that we created earlier.

bool add(beginner_tutorials::AddTwoInts::Request  &req,
         beginner_tutorials::AddTwoInts::Response &res)

This function provides the service for adding two ints, it takes in the request and response type defined in the srv file and returns a boolean.

{
  res.sum = req.a + req.b;
  ROS_INFO("request: x=%ld, y=%ld", (long int)req.a, (long int)req.b);
  ROS_INFO("sending back response: [%ld]", (long int)res.sum);
  return true;
}

Here the two ints are added and stored in the response. Then some information about the request and response are logged. Finally the service returns true when it is complete.

ros::ServiceServer service = n.advertiseService("add_two_ints", add);

Here the service is created and advertised over ROS.
##2.Writing the Client Node
####2.1 The Code
Create the src/add_two_ints_client.cpp file within the beginner_tutorials package and paste the following inside it:

#include "ros/ros.h"
#include "beginner_tutorials/AddTwoInts.h"
#include <cstdlib>

int main(int argc, char **argv)
{
  ros::init(argc, argv, "add_two_ints_client");
  if (argc != 3)
  {
    ROS_INFO("usage: add_two_ints_client X Y");
    return 1;
  }

  ros::NodeHandle n;
  ros::ServiceClient client = n.serviceClient<beginner_tutorials::AddTwoInts>("add_two_ints");
  beginner_tutorials::AddTwoInts srv;
  srv.request.a = atoll(argv[1]);
  srv.request.b = atoll(argv[2]);
  if (client.call(srv))
  {
    ROS_INFO("Sum: %ld", (long int)srv.response.sum);
  }
  else
  {
    ROS_ERROR("Failed to call service add_two_ints");
    return 1;
  }

  return 0;
}
2.2 The Code Explained

Now, let’s break the code down.

ros::ServiceClient client = n.serviceClient<beginner_tutorials::AddTwoInts>("add_two_ints");

This creates a client for the add_two_ints service. The ros::ServiceClient object is used to call the service later on.

  beginner_tutorials::AddTwoInts srv;
  srv.request.a = atoll(argv[1]);
  srv.request.b = atoll(argv[2]);

Here we instantiate(实例化) an autogenerated(自动生成) service class, and assign(分配) values into its request member. A service class contains two members, request and response. It also contains two class definitions, Request and Response.

if (client.call(srv))

This actually calls the service. Since service calls are blocking, it will return once the call is done. If the service call succeeded, call() will return true and the value in srv.response will be valid. If the call did not succeed, call() will return false and the value in srv.response will be invalid.

3. Building your nodes

Again edit the beginner_tutorials CMakeLists.txt located at ~/catkin_ws/src/beginner_tutorials/CMakeLists.txt and add the following at the end:
https://raw.github.com/ros/catkin_tutorials/master/create_package_srvclient/catkin_ws/src/beginner_tutorials/CMakeLists.txt

add_executable(add_two_ints_server src/add_two_ints_server.cpp)
target_link_libraries(add_two_ints_server ${catkin_LIBRARIES})
add_dependencies(add_two_ints_server beginner_tutorials_gencpp)

add_executable(add_two_ints_client src/add_two_ints_client.cpp)
target_link_libraries(add_two_ints_client ${catkin_LIBRARIES})
add_dependencies(add_two_ints_client beginner_tutorials_gencpp)

This will create two executables, add_two_ints_server and add_two_ints_client, which by default will go into package directory of your devel space, located by default at ~/catkin_ws/devel/lib/< package name>. You can invoke executables directly or you can use rosrun to invoke them. They are not placed in ‘< prefix>/bin’ because that would pollute the PATH when installing your package to the system. If you wish for your executable to be on the PATH at installation time, you can setup an install target, see: catkin/CMakeLists.txt
For more detailed description of the CMakeLists.txt file see: catkin/CMakeLists.txt
Now run catkin_make:

# In your catkin workspace
cd ~/catkin_ws
catkin_make

If your build fails for some reason:
make sure you have followed the directions in the previous tutorial: creating the AddTwoInts.srv.

4. Running the nodes

Running nodes requires you have a ROS core started. Open a new shell, and type:

roscore

If all goes well, you should see an output that looks something like this:

... logging to /u/takayama/.ros/logs/83871c9c-934b-11de-a451-
001d927076eb/roslaunch-ads-31831.log
... loading XML file 
[/wg/stor1a/rosbuild/shared_installation/ros/tools/roslaunch/roscore.xml]
Added core node of type [rosout/rosout] in namespace [/]
started roslaunch server http://ads:54367/

SUMMARY
======

NODES

changing ROS_MASTER_URI to [http://ads:11311/] for starting master locally
starting new master (master configured for auto start)
process[master]: started with pid [31874]
ROS_MASTER_URI=http://ads:11311/
setting /run_id to 83871c9c-934b-11de-a451-001d927076eb
+PARAM [/run_id] by /roslaunch
+PARAM [/roslaunch/uris/ads:54367] by /roslaunch
process[rosout-1]: started with pid [31889]
started core service [/rosout]
+SUB [/time] /rosout http://ads:33744/
+SERVICE [/rosout/get_loggers] /rosout http://ads:33744/
+SERVICE [/rosout/set_logger_level] /rosout http://ads:33744/
+PUB [/rosout_agg] /rosout http://ads:33744/
+SUB [/rosout] /rosout http://ads:33744/

Now everything is set to run server and client.

4.1 Running the Server

Start by running the server. Open a new shell and type:
source ~/catkin_ws2/devel/setup.bash

rosrun beginner_tutorials add_two_ints_server

You should see something similar to:

Ready to add two ints.
4.2 Running the Client

Now let’s run the client with the necessary arguments, in another shell:
source ~/catkin_ws2/devel/setup.bash

$ rosrun beginner_tutorials add_two_ints_client 1 3

In the client’s shell, you should see something similar to:

Sum: 4

In the server’s shell, instead, you should see something similar to:

request: x=1, y=3
sending back response: [4]

Now that you have written a simple service and client, let’s examine the simple service and client.

16.Examining the Simple Service and Client

Description: This tutorial examines running the simple service and client
##1.Running the Service
Let’s start by running the service:

$ rosrun beginner_tutorials add_two_ints_server     (C++)
$ rosrun beginner_tutorials add_two_ints_server.py  (Python)

You should see something similar to:

Ready to add two ints.

2.Running the Client

Now let’s run the client with the necessary arguments:

$ rosrun beginner_tutorials add_two_ints_client 1 3     (C++)
$ rosrun beginner_tutorials add_two_ints_client.py 1 3  (Python)

You should see something similar to:

Requesting 1+3
1 + 3 = 4

Now that you’ve successfully run your first server and client, let’s learn how to record and play back data.

3. Further examples on Service and Client nodes

If you want to investigate further and get a hands-on example, you can get one here. A simple Client and Service combination shows the use of custom message types. The Service node is written in C++ while the Client is available in C++, Python and LISP.

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值