Chapter2:ROS基础

R O S 1 {\rm ROS1} ROS1的基础及应用,基于古月的课,各位可以去看,基于 h a w k b o t {\rm hawkbot} hawkbot机器人进行实际操作。
R O S {\rm ROS} ROS版本: R O S 1 {\rm ROS1} ROS1 M e l o d i c {\rm Melodic} Melodic;实际机器人: H a w k b o t {\rm Hawkbot} Hawkbot



1.创建工作空间

  1. 工作空间

    工作空间 ( w o r k s p a c e ) ({\rm workspace}) (workspace)是一个存放工程开发相关文件的文件夹。

    • s r c {\rm src} src:代码空间 ( S o u r c e   S p a c e ) ({\rm Source\ Space}) (Source Space)
    • b u i l d {\rm build} build:编译空间 ( B u i l d   S p a c e ) ({\rm Build\ Space}) (Build Space)
    • d e v e l {\rm devel} devel:开发空间 ( D e v e l o p m e n t   S p a c e ) ({\rm Development\ Space}) (Development Space)
    • i n s t a l l {\rm install} install:安装空间 ( I n s t a l l   S p a c e ) ({\rm Install\ Space}) (Install Space)

    工作空间目录树结构示例:

    tree -L 2 catkin_ws/
    ===============================================================================
    catkin_ws/
    ├── build
    │   ├── atomic_configure
    │   ├── catkin
    │   ├── catkin_generated
    │   ├── CATKIN_IGNORE
    │   ├── catkin_make.cache
    │   ├── CMakeCache.txt
    │   ├── CMakeFiles
    │   ├── cmake_install.cmake
    │   ├── CTestConfiguration.ini
    │   ├── CTestCustom.cmake
    │   ├── CTestTestfile.cmake
    │   ├── gtest
    │   ├── hawkbot
    │   ├── hawkbot_applications
    │   ├── line_follower_turtlebot
    │   ├── Makefile
    │   ├── orb_slam_2_ros
    │   └── test_results
    ├── devel
    │   ├── cmake.lock
    │   ├── env.sh
    │   ├── include
    │   ├── lib
    │   ├── local_setup.bash
    │   ├── local_setup.sh
    │   ├── local_setup.zsh
    │   ├── setup.bash
    │   ├── setup.sh
    │   ├── _setup_util.py
    │   ├── setup.zsh
    │   └── share
    └── src
        ├── CMakeLists.txt -> /opt/ros/melodic/share/catkin/cmake/toplevel.cmake
        ├── hawkbot
        ├── hawkbot_applications
        └── orb_slam_2_ros
    ===============================================================================
    
  2. 创建工作空间

    # 1.创建工作空间
    mkdir -p ~/willard_ws/src
    cd ~/willard_ws/src
    catkin_init_workspace
    
    # 2.编译工作空间
    cd ~/willard_ws/
    catkin_make
    
    # 3.设置环境变量
    source devel/setup.sh
    vim ~/.bashrc
    source ~/.bashrc
    
    # 4.检查环境变量
    echo $ROS_PACKAGE_PATH
    
    # 由于原来存在一个工作空间,因此使用echo命令输出如下:
    # /home/hawkbot/willard_ws/src:/home/hawkbot/catkin_ws/src:/opt/ros/melodic/share
    
  3. 创建功能包

    # 语法:catkin_create_pkg <pkg_name> [depend1] [depend2]..
    # 1.创建功能包
    cd ~/willard_ws/src
    catkin_create_pkg learning_communication std_msgs rospy roscpp
    
    # 2.编译功能包
    cd ~/willard_ws
    catkin_make
    source ~/willard_ws/devel/setup.bash
    
    # 注意:同一个工作空间下,不允许存在同名功能包,不同工作空间下,允许存在同名功能包;
    
  4. 工作空间覆盖机制

    • 工作空间的路径依次在 R O S _ P A C K A G E _ P A T H {\rm ROS\_PACKAGE\_PATH} ROS_PACKAGE_PATH环境变量中记录;
    • 新设置的路径在 R O S _ P A C K A G E _ P A T H {\rm ROS\_PACKAGE\_PATH} ROS_PACKAGE_PATH中自动放在最前端;
    • 运行时, R O S {\rm ROS} ROS优先查找最前端的工作空间中是否存在指定的功能包;
    • 如果不存在,就顺序向后查找其他工作空间;
    # 查看关于ros的所有环境变量
    env | grep ros
    
    # 实践中的结果
    ROS_PACKAGE_PATH=/home/hawkbot/willard_ws/src:/home/hawkbot/catkin_ws/src:/opt/ros/melodic/share
    
    # 可见ROS_PACKAGE_PATH存在三个工作空间的环境变量
    # 执行顺序依次为:willard_ws、catkin_ws
    

2.ROS通信编程

2.1 话题通信编程

1

  1. 创建发布者;
  2. 创建订阅者;
  3. 添加编译选项;
  4. 运行可执行程序;
2.1.1 发布者编程实现
  • 初始化 R O S {\rm ROS} ROS节点;

  • R O S   M a s t e r {\rm ROS\ Master} ROS Master注册节点信息,包括:发布的话题名和话题中的消息类型;

  • 按照一定频率循环发布消息;

  • 编程实现:

    // talker.cpp文件
    
    /**
     *  该例程将发布chatter话题,消息类型为String
    */
    
    #include <sstream>
    #include "ros/ros.h"
    #include "std_msgs/String.h"
    
    int main(int argc, char  **argv)
    {
        // ROS节点初始化
        ros::init(argc, argv, "talker");
    
        // 创建节点句柄
        ros::NodeHandle n;
    
        // 创建一个Publisher, 发布名为chatter的topic, 消息类型为std_msgs::String
        ros::Publisher chatter_pub = n.advertise<std_msgs::String>("chatter", 1000);
    
        // 设置循环的频率
        ros::Rate loop_rate(10);
    
        int count = 0;
        while (ros::ok())
        {
            //  初始化std_msgs::String类型的消息
            std_msgs::String msg;
            std::stringstream ss;
            ss << "Hello.Welcome to FUXI.Technology." << count;
            msg.data = ss.str();
    
            // 发布消息
            ROS_INFO("%s", msg.data.c_str());
            chatter_pub.publish(msg);
    
            // 循环等待回调函数
            ros::spinOnce();
    
            // 按照循环频率延时
            loop_rate.sleep();
            ++count;
        }
    
        return 0;
        
    }
    
2.1.2 订阅者编程实现
  • 初始化 R O S {\rm ROS} ROS节点;

  • 订阅需要的话题;

  • 循环等待话题消息,接收到消息后进入回调函数;

  • 在回调函数中完成消息处理;

  • 编程实现:

    // listener.cpp文件
    
    /**
     *  该例程将订阅chatter话题,消息类型为String
    */
    
    #include "ros/ros.h"
    #include  "std_msgs/String.h"
    
    // 接收到订阅的消息后,进入消息回调函数
    void chatterCallback(const std_msgs::String::ConstPtr& msg)
    {
        // 打印接收到的消息
        ROS_INFO("I heard: [%s]", msg->data.c_str());
    }
    
    int main(int argc, char **argv)
    {
        // 初始化ROS节点
        ros::init(argc, argv, "listener");
    
        // 创建节点句柄
        ros::NodeHandle n;
    
        // 创建一个Subscriber,订阅名为chatter的topic,注册回调函数chatterCallback
        ros::Subscriber sub = n.subscribe("chatter", 1000, chatterCallback);
    
        // 循环等待回调函数
        ros::spin();
    
        return 0;
    }
    
2.1.3 编译代码
  • 设置需要编译的代码和生成的可执行文件;

  • 设置链接库;

  • 设置依赖;

  • 具体实现在 l e a r n i n g c o m m u n i c a t i o n / C M a k e L i s t s . t x t {\rm learning_communication/CMakeLists.txt} learningcommunication/CMakeLists.txt文件:

    cmake_minimum_required(VERSION 2.8.3)
    project(learning_communication)
    
    ## Compile as C++11, supported in ROS Kinetic and newer
    # add_compile_options(-std=c++11)
    
    ## Find catkin macros and libraries
    ## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz)
    ## is used, also find other catkin packages
    find_package(catkin REQUIRED COMPONENTS
      roscpp
      rospy
      std_msgs
    )
    
    ## System dependencies are found with CMake's conventions
    # find_package(Boost REQUIRED COMPONENTS system)
    
    
    ## Uncomment this if the package has a setup.py. This macro ensures
    ## modules and global scripts declared therein get installed
    ## See http://ros.org/doc/api/catkin/html/user_guide/setup_dot_py.html
    # catkin_python_setup()
    
    ################################################
    ## Declare ROS messages, services and actions ##
    ################################################
    
    ## To declare and build messages, services or actions from within this
    ## package, follow these steps:
    ## * Let MSG_DEP_SET be the set of packages whose message types you use in
    ##   your messages/services/actions (e.g. std_msgs, actionlib_msgs, ...).
    ## * In the file package.xml:
    ##   * add a build_depend tag for "message_generation"
    ##   * add a build_depend and a exec_depend tag for each package in MSG_DEP_SET
    ##   * If MSG_DEP_SET isn't empty the following dependency has been pulled in
    ##     but can be declared for certainty nonetheless:
    ##     * add a exec_depend tag for "message_runtime"
    ## * In this file (CMakeLists.txt):
    ##   * add "message_generation" and every package in MSG_DEP_SET to
    ##     find_package(catkin REQUIRED COMPONENTS ...)
    ##   * add "message_runtime" and every package in MSG_DEP_SET to
    ##     catkin_package(CATKIN_DEPENDS ...)
    ##   * uncomment the add_*_files sections below as needed
    ##     and list every .msg/.srv/.action file to be processed
    ##   * uncomment the generate_messages entry below
    ##   * add every package in MSG_DEP_SET to generate_messages(DEPENDENCIES ...)
    
    ## Generate messages in the 'msg' folder
    # add_message_files(
    #   FILES
    #   Message1.msg
    #   Message2.msg
    # )
    
    ## Generate services in the 'srv' folder
    # add_service_files(
    #   FILES
    #   Service1.srv
    #   Service2.srv
    # )
    
    ## Generate actions in the 'action' folder
    # add_action_files(
    #   FILES
    #   Action1.action
    #   Action2.action
    # )
    
    ## Generate added messages and services with any dependencies listed here
    # generate_messages(
    #   DEPENDENCIES
    #   std_msgs
    # )
    
    ################################################
    ## Declare ROS dynamic reconfigure parameters ##
    ################################################
    
    ## To declare and build dynamic reconfigure parameters within this
    ## package, follow these steps:
    ## * In the file package.xml:
    ##   * add a build_depend and a exec_depend tag for "dynamic_reconfigure"
    ## * In this file (CMakeLists.txt):
    ##   * add "dynamic_reconfigure" to
    ##     find_package(catkin REQUIRED COMPONENTS ...)
    ##   * uncomment the "generate_dynamic_reconfigure_options" section below
    ##     and list every .cfg file to be processed
    
    ## Generate dynamic reconfigure parameters in the 'cfg' folder
    # generate_dynamic_reconfigure_options(
    #   cfg/DynReconf1.cfg
    #   cfg/DynReconf2.cfg
    # )
    
    ###################################
    ## catkin specific configuration ##
    ###################################
    ## The catkin_package macro generates cmake config files for your package
    ## Declare things to be passed to dependent projects
    ## INCLUDE_DIRS: uncomment this if your package contains header files
    ## LIBRARIES: libraries you create in this project that dependent projects also need
    ## CATKIN_DEPENDS: catkin_packages dependent projects also need
    ## DEPENDS: system dependencies of this project that dependent projects also need
    catkin_package(
    #  INCLUDE_DIRS include
    #  LIBRARIES learning_communication
    #  CATKIN_DEPENDS roscpp rospy std_msgs
    #  DEPENDS system_lib
    )
    
    ###########
    ## Build ##
    ###########
    
    ## Specify additional locations of header files
    ## Your package locations should be listed before other locations
    include_directories(
    # include
      ${catkin_INCLUDE_DIRS}
    )
    
    ## Declare a C++ library
    # add_library(${PROJECT_NAME}
    #   src/${PROJECT_NAME}/learning_communication.cpp
    # )
    
    ## Add cmake target dependencies of the library
    ## as an example, code may need to be generated before libraries
    ## either from message generation or dynamic reconfigure
    # add_dependencies(${PROJECT_NAME} ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})
    
    ## Declare a C++ executable
    ## With catkin_make all packages are built within a single CMake context
    ## The recommended prefix ensures that target names across packages don't collide
    # add_executable(${PROJECT_NAME}_node src/learning_communication_node.cpp)
    
    # 新增加的链接库和依赖
    # ---------------------------------------------------
    add_executable(talker src/talker.cpp)
    target_link_libraries(talker ${catkin_LIBRARIES})
    # add_dependencies(talker ${PROJECT_NAME}_generate_messages_cpp)
    add_executable(listener src/listener.cpp)
    target_link_libraries(listener ${catkin_LIBRARIES})
    # add_dependencies(talker ${PROJECT_NAME}_generate_messages_cpp)
    # ---------------------------------------------------
    
    ## Rename C++ executable without prefix
    ## The above recommended prefix causes long target names, the following renames the
    ## target back to the shorter version for ease of user use
    ## e.g. "rosrun someones_pkg node" instead of "rosrun someones_pkg someones_pkg_node"
    # set_target_properties(${PROJECT_NAME}_node PROPERTIES OUTPUT_NAME node PREFIX "")
    
    ## Add cmake target dependencies of the executable
    ## same as for the library above
    # add_dependencies(${PROJECT_NAME}_node ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})
    
    ## Specify libraries to link a library or executable target against
    # target_link_libraries(${PROJECT_NAME}_node
    #   ${catkin_LIBRARIES}
    # )
    
    #############
    ## Install ##
    #############
    
    # all install targets should use catkin DESTINATION variables
    # See http://ros.org/doc/api/catkin/html/adv_user_guide/variables.html
    
    ## Mark executable scripts (Python etc.) for installation
    ## in contrast to setup.py, you can choose the destination
    # install(PROGRAMS
    #   scripts/my_python_script
    #   DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
    # )
    
    ## Mark executables for installation
    ## See http://docs.ros.org/melodic/api/catkin/html/howto/format1/building_executables.html
    # install(TARGETS ${PROJECT_NAME}_node
    #   RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
    # )
    
    ## Mark libraries for installation
    ## See http://docs.ros.org/melodic/api/catkin/html/howto/format1/building_libraries.html
    # install(TARGETS ${PROJECT_NAME}
    #   ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
    #   LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
    #   RUNTIME DESTINATION ${CATKIN_GLOBAL_BIN_DESTINATION}
    # )
    
    ## Mark cpp header files for installation
    # install(DIRECTORY include/${PROJECT_NAME}/
    #   DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION}
    #   FILES_MATCHING PATTERN "*.h"
    #   PATTERN ".svn" EXCLUDE
    # )
    
    ## Mark other files for installation (e.g. launch and bag files, etc.)
    # install(FILES
    #   # myfile1
    #   # myfile2
    #   DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}
    # )
    
    #############
    ## Testing ##
    #############
    
    ## Add gtest based cpp test target and link libraries
    # catkin_add_gtest(${PROJECT_NAME}-test test/test_learning_communication.cpp)
    # if(TARGET ${PROJECT_NAME}-test)
    #   target_link_libraries(${PROJECT_NAME}-test ${PROJECT_NAME})
    # endif()
    
    ## Add folders to be run by python nosetests
    # catkin_add_nosetests(test)
    
    # 1.编写发布者talker.cpp
    # 2.编写订阅者listener.cpp
    # 3.在CMakeLists.txt文件中设置链接库和依赖;
    # 4.切换到工作空间进行编译;
    cd ~/Willard_ws/
    catkin_make
    # 5.运行可执行文件,注:没有.cpp后缀;
    roscore
    rosrun learning_communication talker
    rosrun learning_communication listener
    
    # 注意:代码文件放在功能包learning_communication/src下;
    # 设置链接库和依赖是在learning_communication/CMakeLists.txt;
    
  • 实现效果如下:

    2

2.1.4 自定义话题消息
# 1.在learning_communication目录下新建msg目录
mkdir msg

# 2.定义msg文件;
# Person.msg
string name
uint8 sex
uint8 age

uint8 unknown = 0
uint8 male = 1
uint8 female = 2

# 3.在package.xml中添加功能包依赖
<build_depend>message_generation</build_depend>
<exec_depend>message_runtime</exec_depend>

# 4.在CMakeLists.txt添加编译选项
find_package(... message_generation)
catkin_package(CATKIN_DEPENDS roscpp rospy std_msgs message_runtime)
add_message_files(FILES Person.msg)
generate_messages(DEPENDENCIES std_msgs)

# 5.编译
cd ~/willard_ws/
catkin_make

# 6.编译成功后,查看Person.msg信息
rosmsg show Person
# Person.msg
string name
uint8 sex
uint8 age

uint8 unknown = 0
uint8 male = 1
uint8 female = 2
<!-- packages.xml -->

<?xml version="1.0"?>
<package format="2">
  <name>learning_communication</name>
  <version>0.0.0</version>
  <description>The learning_communication package</description>

  <!-- One maintainer tag required, multiple allowed, one person per tag -->
  <!-- Example:  -->
  <!-- <maintainer email="[email protected]">Jane Doe</maintainer> -->
  <maintainer email="[email protected]">hawkbot</maintainer>


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


  <!-- Url tags are optional, but multiple are allowed, one per tag -->
  <!-- Optional attribute type can be: website, bugtracker, or repository -->
  <!-- Example: -->
  <!-- <url type="website">http://wiki.ros.org/learning_communication</url> -->


  <!-- Author tags are optional, multiple are allowed, one per tag -->
  <!-- Authors do not have to be maintainers, but could be -->
  <!-- Example: -->
  <!-- <author email="[email protected]">Jane Doe</author> -->


  <!-- The *depend tags are used to specify dependencies -->
  <!-- Dependencies can be catkin packages or system dependencies -->
  <!-- Examples: -->
  <!-- Use depend as a shortcut for packages that are both build and exec dependencies -->
  <!--   <depend>roscpp</depend> -->
  <!--   Note that this is equivalent to the following: -->
  <!--   <build_depend>roscpp</build_depend> -->
  <!--   <exec_depend>roscpp</exec_depend> -->
  <!-- Use build_depend for packages you need at compile time: -->
  <!--   <build_depend>message_generation</build_depend> -->
  <!-- Use build_export_depend for packages you need in order to build against this package: -->
  <!--   <build_export_depend>message_generation</build_export_depend> -->
  <!-- Use buildtool_depend for build tool packages: -->
  <!--   <buildtool_depend>catkin</buildtool_depend> -->
  <!-- Use exec_depend for packages you need at runtime: -->
  <!--   <exec_depend>message_runtime</exec_depend> -->
  <!-- Use test_depend for packages you need only for testing: -->
  <!--   <test_depend>gtest</test_depend> -->
  <!-- Use doc_depend for packages you need only for building documentation: -->
  <!--   <doc_depend>doxygen</doc_depend> -->
  <buildtool_depend>catkin</buildtool_depend>
  <build_depend>roscpp</build_depend>
  <build_depend>rospy</build_depend>
  <build_depend>std_msgs</build_depend>
  <build_export_depend>roscpp</build_export_depend>
  <build_export_depend>rospy</build_export_depend>
  <build_export_depend>std_msgs</build_export_depend>
  <exec_depend>roscpp</exec_depend>
  <exec_depend>rospy</exec_depend>
  <exec_depend>std_msgs</exec_depend>

  <!-- 新增的依赖 -->
  <build_depend>message_generation</build_depend>
  <exec_depend>message_runtime</exec_depend>


  <!-- The export tag contains other, unspecified, tags -->
  <export>
    <!-- Other tools can request additional information be placed here -->

  </export>
</package>
# CMakeLists.txt文件

cmake_minimum_required(VERSION 2.8.3)
project(learning_communication)

## Compile as C++11, supported in ROS Kinetic and newer
# add_compile_options(-std=c++11)

## Find catkin macros and libraries
## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz)
## is used, also find other catkin packages

# =============================================
# 新增message_generation
find_package(catkin REQUIRED COMPONENTS
  roscpp
  rospy
  std_msgs
  message_generation
)
# =============================================

## System dependencies are found with CMake's conventions
# find_package(Boost REQUIRED COMPONENTS system)


## Uncomment this if the package has a setup.py. This macro ensures
## modules and global scripts declared therein get installed
## See http://ros.org/doc/api/catkin/html/user_guide/setup_dot_py.html
# catkin_python_setup()

################################################
## Declare ROS messages, services and actions ##
################################################

## To declare and build messages, services or actions from within this
## package, follow these steps:
## * Let MSG_DEP_SET be the set of packages whose message types you use in
##   your messages/services/actions (e.g. std_msgs, actionlib_msgs, ...).
## * In the file package.xml:
##   * add a build_depend tag for "message_generation"
##   * add a build_depend and a exec_depend tag for each package in MSG_DEP_SET
##   * If MSG_DEP_SET isn't empty the following dependency has been pulled in
##     but can be declared for certainty nonetheless:
##     * add a exec_depend tag for "message_runtime"
## * In this file (CMakeLists.txt):
##   * add "message_generation" and every package in MSG_DEP_SET to
##     find_package(catkin REQUIRED COMPONENTS ...)
##   * add "message_runtime" and every package in MSG_DEP_SET to
##     catkin_package(CATKIN_DEPENDS ...)
##   * uncomment the add_*_files sections below as needed
##     and list every .msg/.srv/.action file to be processed
##   * uncomment the generate_messages entry below
##   * add every package in MSG_DEP_SET to generate_messages(DEPENDENCIES ...)

## Generate messages in the 'msg' folder

# =============================================
# 新增内容的位置
add_message_files(
    FILES
    Person.msg
#   Message1.msg
#   Message2.msg
)
# =============================================

## Generate services in the 'srv' folder
# add_service_files(
#   FILES
#   Service1.srv
#   Service2.srv
# )

## Generate actions in the 'action' folder
# add_action_files(
#   FILES
#   Action1.action
#   Action2.action
# )

## Generate added messages and services with any dependencies listed here

# =============================================
# 新增内容的位置
generate_messages(
    DEPENDENCIES
    std_msgs
)
# =============================================

################################################
## Declare ROS dynamic reconfigure parameters ##
################################################

## To declare and build dynamic reconfigure parameters within this
## package, follow these steps:
## * In the file package.xml:
##   * add a build_depend and a exec_depend tag for "dynamic_reconfigure"
## * In this file (CMakeLists.txt):
##   * add "dynamic_reconfigure" to
##     find_package(catkin REQUIRED COMPONENTS ...)
##   * uncomment the "generate_dynamic_reconfigure_options" section below
##     and list every .cfg file to be processed

## Generate dynamic reconfigure parameters in the 'cfg' folder
# generate_dynamic_reconfigure_options(
#   cfg/DynReconf1.cfg
#   cfg/DynReconf2.cfg
# )

###################################
## catkin specific configuration ##
###################################
## The catkin_package macro generates cmake config files for your package
## Declare things to be passed to dependent projects
## INCLUDE_DIRS: uncomment this if your package contains header files
## LIBRARIES: libraries you create in this project that dependent projects also need
## CATKIN_DEPENDS: catkin_packages dependent projects also need
## DEPENDS: system dependencies of this project that dependent projects also need

# =============================================
# 需要新增内容的位置
catkin_package(
#  INCLUDE_DIRS include
#  LIBRARIES learning_communication
   CATKIN_DEPENDS roscpp rospy std_msgs message_runtime
#  DEPENDS system_lib
)
# =============================================

###########
## Build ##
###########

## Specify additional locations of header files
## Your package locations should be listed before other locations
include_directories(
# include
  ${catkin_INCLUDE_DIRS}
)

## Declare a C++ library
# add_library(${PROJECT_NAME}
#   src/${PROJECT_NAME}/learning_communication.cpp
# )

## Add cmake target dependencies of the library
## as an example, code may need to be generated before libraries
## either from message generation or dynamic reconfigure
# add_dependencies(${PROJECT_NAME} ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})

## Declare a C++ executable
## With catkin_make all packages are built within a single CMake context
## The recommended prefix ensures that target names across packages don't collide
# add_executable(${PROJECT_NAME}_node src/learning_communication_node.cpp)

# 新增加的链接库和依赖
add_executable(talker src/talker.cpp)
target_link_libraries(talker ${catkin_LIBRARIES})
# add_dependencies(talker ${PROJECT_NAME}_generate_messages_cpp)
add_executable(listener src/listener.cpp)
target_link_libraries(listener ${catkin_LIBRARIES})
# add_dependencies(talker ${PROJECT_NAME}_generate_messages_cpp)


## Rename C++ executable without prefix
## The above recommended prefix causes long target names, the following renames the
## target back to the shorter version for ease of user use
## e.g. "rosrun someones_pkg node" instead of "rosrun someones_pkg someones_pkg_node"
# set_target_properties(${PROJECT_NAME}_node PROPERTIES OUTPUT_NAME node PREFIX "")

## Add cmake target dependencies of the executable
## same as for the library above
# add_dependencies(${PROJECT_NAME}_node ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})

## Specify libraries to link a library or executable target against
# target_link_libraries(${PROJECT_NAME}_node
#   ${catkin_LIBRARIES}
# )

#############
## Install ##
#############

# all install targets should use catkin DESTINATION variables
# See http://ros.org/doc/api/catkin/html/adv_user_guide/variables.html

## Mark executable scripts (Python etc.) for installation
## in contrast to setup.py, you can choose the destination
# install(PROGRAMS
#   scripts/my_python_script
#   DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
# )

## Mark executables for installation
## See http://docs.ros.org/melodic/api/catkin/html/howto/format1/building_executables.html
# install(TARGETS ${PROJECT_NAME}_node
#   RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
# )

## Mark libraries for installation
## See http://docs.ros.org/melodic/api/catkin/html/howto/format1/building_libraries.html
# install(TARGETS ${PROJECT_NAME}
#   ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
#   LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
#   RUNTIME DESTINATION ${CATKIN_GLOBAL_BIN_DESTINATION}
# )

## Mark cpp header files for installation
# install(DIRECTORY include/${PROJECT_NAME}/
#   DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION}
#   FILES_MATCHING PATTERN "*.h"
#   PATTERN ".svn" EXCLUDE
# )

## Mark other files for installation (e.g. launch and bag files, etc.)
# install(FILES
#   # myfile1
#   # myfile2
#   DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}
# )

#############
## Testing ##
#############

## Add gtest based cpp test target and link libraries
# catkin_add_gtest(${PROJECT_NAME}-test test/test_learning_communication.cpp)
# if(TARGET ${PROJECT_NAME}-test)
#   target_link_libraries(${PROJECT_NAME}-test ${PROJECT_NAME})
# endif()

## Add folders to be run by python nosetests
# catkin_add_nosetests(test)
2.2 服务通信编程

3

  1. 创建服务器;
  2. 创建客户端;
  3. 添加编译选项;
  4. 运行可执行文件;
2.2.1 自定义服务请求与应答
# 1.定义srv文件,放置在learning_communication/srv目录下
roscd learning_communication/
mkdir srv
cd srv

# 2.定义Add.srv文件
gedit Add.srv

# 3.在package.xml中添加功能包依赖
<build_depend>message_generation</build_depend>
<exec_depend>message_runtime</exec_depend>

# 4.在CMakeLists.txt添加编译选项
find_package(... message_generation)
catkin_package(CATKIN_DEPENDS roscpp rospy std_msgs message_runtime)
add_service_files(FILES Add.srv)

# 5.编译
cd ~/willard_ws/
catkin_make

# 注:自定义服务过程和自定义消息过程类似;
# Add.srv文件
int64 a
int64 b
int64 c
---
int64 sum
<!-- packages.xml文件 -->

<?xml version="1.0"?>
<package format="2">
  <name>learning_communication</name>
  <version>0.0.0</version>
  <description>The learning_communication package</description>

  <!-- One maintainer tag required, multiple allowed, one person per tag -->
  <!-- Example:  -->
  <!-- <maintainer email="[email protected]">Jane Doe</maintainer> -->
  <maintainer email="[email protected]">hawkbot</maintainer>


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


  <!-- Url tags are optional, but multiple are allowed, one per tag -->
  <!-- Optional attribute type can be: website, bugtracker, or repository -->
  <!-- Example: -->
  <!-- <url type="website">http://wiki.ros.org/learning_communication</url> -->


  <!-- Author tags are optional, multiple are allowed, one per tag -->
  <!-- Authors do not have to be maintainers, but could be -->
  <!-- Example: -->
  <!-- <author email="[email protected]">Jane Doe</author> -->


  <!-- The *depend tags are used to specify dependencies -->
  <!-- Dependencies can be catkin packages or system dependencies -->
  <!-- Examples: -->
  <!-- Use depend as a shortcut for packages that are both build and exec dependencies -->
  <!--   <depend>roscpp</depend> -->
  <!--   Note that this is equivalent to the following: -->
  <!--   <build_depend>roscpp</build_depend> -->
  <!--   <exec_depend>roscpp</exec_depend> -->
  <!-- Use build_depend for packages you need at compile time: -->
  <!--   <build_depend>message_generation</build_depend> -->
  <!-- Use build_export_depend for packages you need in order to build against this package: -->
  <!--   <build_export_depend>message_generation</build_export_depend> -->
  <!-- Use buildtool_depend for build tool packages: -->
  <!--   <buildtool_depend>catkin</buildtool_depend> -->
  <!-- Use exec_depend for packages you need at runtime: -->
  <!--   <exec_depend>message_runtime</exec_depend> -->
  <!-- Use test_depend for packages you need only for testing: -->
  <!--   <test_depend>gtest</test_depend> -->
  <!-- Use doc_depend for packages you need only for building documentation: -->
  <!--   <doc_depend>doxygen</doc_depend> -->
  <buildtool_depend>catkin</buildtool_depend>
  <build_depend>roscpp</build_depend>
  <build_depend>rospy</build_depend>
  <build_depend>std_msgs</build_depend>
  <build_export_depend>roscpp</build_export_depend>
  <build_export_depend>rospy</build_export_depend>
  <build_export_depend>std_msgs</build_export_depend>
  <exec_depend>roscpp</exec_depend>
  <exec_depend>rospy</exec_depend>
  <exec_depend>std_msgs</exec_depend>

  <!-- 新增的依赖 -->
  <build_depend>message_generation</build_depend>
  <exec_depend>message_runtime</exec_depend>


  <!-- The export tag contains other, unspecified, tags -->
  <export>
    <!-- Other tools can request additional information be placed here -->

  </export>
</package>
# CMakeLists.txt文件
cmake_minimum_required(VERSION 2.8.3)
project(learning_communication)

## Compile as C++11, supported in ROS Kinetic and newer
# add_compile_options(-std=c++11)

## Find catkin macros and libraries
## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz)
## is used, also find other catkin packages

# =============================================
# 新增message_generation
find_package(catkin REQUIRED COMPONENTS
  roscpp
  rospy
  std_msgs
  message_generation
)
# =============================================

## System dependencies are found with CMake's conventions
# find_package(Boost REQUIRED COMPONENTS system)


## Uncomment this if the package has a setup.py. This macro ensures
## modules and global scripts declared therein get installed
## See http://ros.org/doc/api/catkin/html/user_guide/setup_dot_py.html
# catkin_python_setup()

################################################
## Declare ROS messages, services and actions ##
################################################

## To declare and build messages, services or actions from within this
## package, follow these steps:
## * Let MSG_DEP_SET be the set of packages whose message types you use in
##   your messages/services/actions (e.g. std_msgs, actionlib_msgs, ...).
## * In the file package.xml:
##   * add a build_depend tag for "message_generation"
##   * add a build_depend and a exec_depend tag for each package in MSG_DEP_SET
##   * If MSG_DEP_SET isn't empty the following dependency has been pulled in
##     but can be declared for certainty nonetheless:
##     * add a exec_depend tag for "message_runtime"
## * In this file (CMakeLists.txt):
##   * add "message_generation" and every package in MSG_DEP_SET to
##     find_package(catkin REQUIRED COMPONENTS ...)
##   * add "message_runtime" and every package in MSG_DEP_SET to
##     catkin_package(CATKIN_DEPENDS ...)
##   * uncomment the add_*_files sections below as needed
##     and list every .msg/.srv/.action file to be processed
##   * uncomment the generate_messages entry below
##   * add every package in MSG_DEP_SET to generate_messages(DEPENDENCIES ...)

## Generate messages in the 'msg' folder

# =============================================
# 新增内容的位置
add_message_files(
    FILES
    Person.msg
#   Message1.msg
#   Message2.msg
)
# =============================================

## Generate services in the 'srv' folder

# =============================================
# 新增内容的位置
add_service_files(
    FILES
    Add.srv
#   Service1.srv
#   Service2.srv
)
# =============================================

## Generate actions in the 'action' folder
# add_action_files(
#   FILES
#   Action1.action
#   Action2.action
# )

## Generate added messages and services with any dependencies listed here

# =============================================
# 新增内容的位置
generate_messages(
    DEPENDENCIES
    std_msgs
)
# =============================================

################################################
## Declare ROS dynamic reconfigure parameters ##
################################################

## To declare and build dynamic reconfigure parameters within this
## package, follow these steps:
## * In the file package.xml:
##   * add a build_depend and a exec_depend tag for "dynamic_reconfigure"
## * In this file (CMakeLists.txt):
##   * add "dynamic_reconfigure" to
##     find_package(catkin REQUIRED COMPONENTS ...)
##   * uncomment the "generate_dynamic_reconfigure_options" section below
##     and list every .cfg file to be processed

## Generate dynamic reconfigure parameters in the 'cfg' folder
# generate_dynamic_reconfigure_options(
#   cfg/DynReconf1.cfg
#   cfg/DynReconf2.cfg
# )

###################################
## catkin specific configuration ##
###################################
## The catkin_package macro generates cmake config files for your package
## Declare things to be passed to dependent projects
## INCLUDE_DIRS: uncomment this if your package contains header files
## LIBRARIES: libraries you create in this project that dependent projects also need
## CATKIN_DEPENDS: catkin_packages dependent projects also need
## DEPENDS: system dependencies of this project that dependent projects also need

# =============================================
# 需要新增内容的位置
catkin_package(
#  INCLUDE_DIRS include
#  LIBRARIES learning_communication
   CATKIN_DEPENDS roscpp rospy std_msgs message_runtime
#  DEPENDS system_lib
)
# =============================================

###########
## Build ##
###########

## Specify additional locations of header files
## Your package locations should be listed before other locations
include_directories(
# include
  ${catkin_INCLUDE_DIRS}
)

## Declare a C++ library
# add_library(${PROJECT_NAME}
#   src/${PROJECT_NAME}/learning_communication.cpp
# )

## Add cmake target dependencies of the library
## as an example, code may need to be generated before libraries
## either from message generation or dynamic reconfigure
# add_dependencies(${PROJECT_NAME} ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})

## Declare a C++ executable
## With catkin_make all packages are built within a single CMake context
## The recommended prefix ensures that target names across packages don't collide
# add_executable(${PROJECT_NAME}_node src/learning_communication_node.cpp)

# 新增加的链接库和依赖
add_executable(talker src/talker.cpp)
target_link_libraries(talker ${catkin_LIBRARIES})
# add_dependencies(talker ${PROJECT_NAME}_generate_messages_cpp)
add_executable(listener src/listener.cpp)
target_link_libraries(listener ${catkin_LIBRARIES})
# add_dependencies(talker ${PROJECT_NAME}_generate_messages_cpp)


## Rename C++ executable without prefix
## The above recommended prefix causes long target names, the following renames the
## target back to the shorter version for ease of user use
## e.g. "rosrun someones_pkg node" instead of "rosrun someones_pkg someones_pkg_node"
# set_target_properties(${PROJECT_NAME}_node PROPERTIES OUTPUT_NAME node PREFIX "")

## Add cmake target dependencies of the executable
## same as for the library above
# add_dependencies(${PROJECT_NAME}_node ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})

## Specify libraries to link a library or executable target against
# target_link_libraries(${PROJECT_NAME}_node
#   ${catkin_LIBRARIES}
# )

#############
## Install ##
#############

# all install targets should use catkin DESTINATION variables
# See http://ros.org/doc/api/catkin/html/adv_user_guide/variables.html

## Mark executable scripts (Python etc.) for installation
## in contrast to setup.py, you can choose the destination
# install(PROGRAMS
#   scripts/my_python_script
#   DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
# )

## Mark executables for installation
## See http://docs.ros.org/melodic/api/catkin/html/howto/format1/building_executables.html
# install(TARGETS ${PROJECT_NAME}_node
#   RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
# )

## Mark libraries for installation
## See http://docs.ros.org/melodic/api/catkin/html/howto/format1/building_libraries.html
# install(TARGETS ${PROJECT_NAME}
#   ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
#   LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
#   RUNTIME DESTINATION ${CATKIN_GLOBAL_BIN_DESTINATION}
# )

## Mark cpp header files for installation
# install(DIRECTORY include/${PROJECT_NAME}/
#   DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION}
#   FILES_MATCHING PATTERN "*.h"
#   PATTERN ".svn" EXCLUDE
# )

## Mark other files for installation (e.g. launch and bag files, etc.)
# install(FILES
#   # myfile1
#   # myfile2
#   DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}
# )

#############
## Testing ##
#############

## Add gtest based cpp test target and link libraries
# catkin_add_gtest(${PROJECT_NAME}-test test/test_learning_communication.cpp)
# if(TARGET ${PROJECT_NAME}-test)
#   target_link_libraries(${PROJECT_NAME}-test ${PROJECT_NAME})
# endif()

## Add folders to be run by python nosetests
# catkin_add_nosetests(test)
2.2.2 服务器编程实现
  • 初始化 R O S {\rm ROS} ROS节点;

  • 创建 S e r v e r {\rm Server} Server实例;

  • 循环等待服务请求,进入回调函数;

  • 在回调函数中完成服务功能的处理,并反馈应答数据;

  • 服务器编程实现:

    /**
     * Add Server
     */
    
    #include "ros/ros.h"
    #include "learning_communication/Add.h"
    
    // service回调函数,输入参数req,输出参数res
    bool add(learning_communication::Add::Request &req,
             learning_communication::Add::Response &res)
    {
        // 将输入参数中的请求数据相加,结果放到应答变量中
        res.sum = req.a + req.b + req.c;
        ROS_INFO("request: x=%ld, y=%ld,z=%ld", (long int)req.a, (long int)req.b, (long int)req.c);
        ROS_INFO("sending back response: [%ld]", (long int)res.sum);
    
        return true;
    }
    
    int main(int argc, char **argv)
    {
        // ROS节点初始化
        ros::init(argc, argv, "add_server");
    
        // 创建节点句柄
        ros::NodeHandle n;
    
        // 创建一个名为add_three_ints的server,注册回调函数add()
        ros::ServiceServer service = n.advertiseService("add_three_ints", add);
    
        // 循环等待回调函数
        ROS_INFO("Ready to add three ints.");
        ros::spin();
    
        return 0;
    }
    
2.2.3 客户端编程实现
  • 初始化 R O S {\rm ROS} ROS节点;

  • 创建一个 C l i e n t {\rm Client} Client实例;

  • 发布服务请求数据;

  • 等待 S e r v e r {\rm Server} Server处理后的应答结果;

  • 客户端编程实现:

    /**
     *  Add client
     */
    
    #include <cstdlib>
    #include "ros/ros.h"
    #include "learning_communication/Add.h"
    
    int main(int argc, char **argv)
    {
        // ROS节点初始化
        ros::init(argc, argv, "add_client");
    
        // 从终端命令行获取三个加数
        if (argc != 4)
        {
            ROS_INFO("usage: add_client X Y Z");
            return 1;
        }
    
        // 创建节点句柄
        ros::NodeHandle n;
    
        // 创建一个client,请求add service,service消息类型是learning_communication::Add;
        ros::ServiceClient client = n.serviceClient<learning_communication::Add>("add_three_ints");     // 注意和server注册的服务名一致
    
        // 创建learning_communication::Add类型的service消息
        learning_communication::Add srv;
        srv.request.a = atoll(argv[1]);
        srv.request.b = atoll(argv[2]);
        srv.request.c = atoll(argv[3]);
    
        // 发布service请求,等待加法运算的应答结果
        if (client.call(srv))
        {
            ROS_INFO("Sum: %ld", (long int)srv.response.sum);
        }
        else
        {
            ROS_ERROR("Failed to call service add_three_ints");
            return 1;
        }
    
        return 0;
    }
    
2.2.4 编译代码
  • 设置需要编译的代码和生成的可执行文件;

  • 设置链接库;

  • 设置依赖;

  • 具体实现:

    # CMakeLists.txt对应位置添加如下内容
    add_executable(server src/server.cpp)
    target_link_libraries(server ${catkin_LIBRARIES})
    add_dependencies(server ${PROJECT_NAME}_gencpp)
    
    add_executable(client src/client.cpp)
    target_link_libraries(client ${catkin_LIBRARIES})
    add_dependencies(client ${PROJECT_NAME}_gencpp)
    
  • 服务建立过程:

    # 1.定义服务的请求与应答文件;
    # 2.编写服务器端代码;
    # 3.编写客户端代码;
    # 4.设置需要编译的代码和生成的可执行文件,设置链接库,设置依赖;
    # 5.工作空间下编译;
    cd ~/willard_ws/
    catkin_make
    
    # 6.运行可执行文件
    roscore		# 启动master
    rosrun learning_communication server
    rosrun learning_commnuication client 1 2 3
    
  • 实现效果图:

    4

2.3 动作通信编程
2.3.1 动作通信机制基础
  1. 动作 ( a c t i o n ) ({\rm action}) (action)的定义

    • 一种问答通信机制;

    • 带有连续反馈;

    • 可以在任务过程中止运行;

    • 基于 R O S {\rm ROS} ROS的消息机制实现;

    • 动作 ( a c t i o n ) ({\rm action}) (action)通信机制:

      5

  2. A c t i o n {\rm Action} Action接口定义

    • g o a l {\rm goal} goal:发布任务目标;

    • c a n c e l {\rm cancel} cancel:请求取消任务;

    • s t a t u s {\rm status} status:通知客户端当前的状态;

    • f e e d b a c k {\rm feedback} feedback:周期反馈任务运行的监控数据;

    • r e s u l t {\rm result} result:向客户端发送任务的执行结果,只发布一次;

    • 示意图如下:

      6

2.3.2 自定义动作消息
# 1.定义action文件;
# DoDishes.action
------------------------------
# 定义目标信息
uint32 dishwasher_id
---
# 定义结果信息
uint32 total_dishes_cleaned
---
# 定义周期反馈的消息
float32 percent_complete
------------------------------

# 2.在package.xml中添加功能包依赖;
<build_depend>actionlib</build_depend>
<build_depend>actionlib_msgs</build_depend>
<exec_depend>actionlib</exec_depend>
<exec_depend>actionlib_msgs</exec_depend>

# 3.在CMakeLists.txt添加编译选项
# 注意:在原来的文件中加入一些依赖即可,不用另起一行重新加入这些信息;
# 直接找到find_package(...actionlib_msgs actionlib)
find_package(catkin REQUIRED actionlib_msgs actionlib)
add_action_files(DIRECTORY action FILES DoDishes.action)
generate_messages(DEPENDENCIES actionlib_msgs)
# 1.创建action目录
roscd learning_communication/
mkdir action

# 2.定义.action文件
cd action
touch DoDishes.action
gedit DoDishes.action

# 3.在package.xml中添加功能包依赖
gedit package.xml

# 4.在CMakeLists.txt文件添加编译选项
gedit CMakeLists.txt

# 5.编译
cd ~/willard_ws/
catkin_make
# DoDishes.action文件
# 注意.action文件的定义格式

# 定义目标信息
uint32 dishwasher_id
---
# 定义结果信息
uint32 total_dishes_cleaned
---
# 定义周期反馈消息
float32 percent_complete
<!-- package.xml文件 -->

<?xml version="1.0"?>
<package format="2">
  <name>learning_communication</name>
  <version>0.0.0</version>
  <description>The learning_communication package</description>

  <!-- One maintainer tag required, multiple allowed, one person per tag -->
  <!-- Example:  -->
  <!-- <maintainer email="[email protected]">Jane Doe</maintainer> -->
  <maintainer email="[email protected]">hawkbot</maintainer>


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


  <!-- Url tags are optional, but multiple are allowed, one per tag -->
  <!-- Optional attribute type can be: website, bugtracker, or repository -->
  <!-- Example: -->
  <!-- <url type="website">http://wiki.ros.org/learning_communication</url> -->


  <!-- Author tags are optional, multiple are allowed, one per tag -->
  <!-- Authors do not have to be maintainers, but could be -->
  <!-- Example: -->
  <!-- <author email="[email protected]">Jane Doe</author> -->


  <!-- The *depend tags are used to specify dependencies -->
  <!-- Dependencies can be catkin packages or system dependencies -->
  <!-- Examples: -->
  <!-- Use depend as a shortcut for packages that are both build and exec dependencies -->
  <!--   <depend>roscpp</depend> -->
  <!--   Note that this is equivalent to the following: -->
  <!--   <build_depend>roscpp</build_depend> -->
  <!--   <exec_depend>roscpp</exec_depend> -->
  <!-- Use build_depend for packages you need at compile time: -->
  <!--   <build_depend>message_generation</build_depend> -->
  <!-- Use build_export_depend for packages you need in order to build against this package: -->
  <!--   <build_export_depend>message_generation</build_export_depend> -->
  <!-- Use buildtool_depend for build tool packages: -->
  <!--   <buildtool_depend>catkin</buildtool_depend> -->
  <!-- Use exec_depend for packages you need at runtime: -->
  <!--   <exec_depend>message_runtime</exec_depend> -->
  <!-- Use test_depend for packages you need only for testing: -->
  <!--   <test_depend>gtest</test_depend> -->
  <!-- Use doc_depend for packages you need only for building documentation: -->
  <!--   <doc_depend>doxygen</doc_depend> -->
  <buildtool_depend>catkin</buildtool_depend>
  <build_depend>roscpp</build_depend>
  <build_depend>rospy</build_depend>
  <build_depend>std_msgs</build_depend>
  <build_export_depend>roscpp</build_export_depend>
  <build_export_depend>rospy</build_export_depend>
  <build_export_depend>std_msgs</build_export_depend>
  <exec_depend>roscpp</exec_depend>
  <exec_depend>rospy</exec_depend>
  <exec_depend>std_msgs</exec_depend>

  <!-- 新增的依赖 -->
  <build_depend>message_generation</build_depend>
  <exec_depend>message_runtime</exec_depend>

  <!-- action新增的依赖 -->
  <build_depend>actionlib</build_depend>
  <build_depend>actionlib_msgs</build_depend>
  <exec_depend>actionlib</exec_depend>
  <exec_depend>actionlib_msgs</exec_depend>


  <!-- The export tag contains other, unspecified, tags -->
  <export>
    <!-- Other tools can request additional information be placed here -->

  </export>
</package>
# CMakeLists.txt文件

cmake_minimum_required(VERSION 2.8.3)
project(learning_communication)

## Compile as C++11, supported in ROS Kinetic and newer
# add_compile_options(-std=c++11)

## Find catkin macros and libraries
## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz)
## is used, also find other catkin packages

# =============================================
# 新增message_generation
find_package(catkin REQUIRED COMPONENTS
  roscpp
  rospy
  std_msgs
  message_generation
  # ==action新增依赖==
  actionlib_msgs
  actionlib
  # ==================
)
# =============================================

## System dependencies are found with CMake's conventions
# find_package(Boost REQUIRED COMPONENTS system)


## Uncomment this if the package has a setup.py. This macro ensures
## modules and global scripts declared therein get installed
## See http://ros.org/doc/api/catkin/html/user_guide/setup_dot_py.html
# catkin_python_setup()

################################################
## Declare ROS messages, services and actions ##
################################################

## To declare and build messages, services or actions from within this
## package, follow these steps:
## * Let MSG_DEP_SET be the set of packages whose message types you use in
##   your messages/services/actions (e.g. std_msgs, actionlib_msgs, ...).
## * In the file package.xml:
##   * add a build_depend tag for "message_generation"
##   * add a build_depend and a exec_depend tag for each package in MSG_DEP_SET
##   * If MSG_DEP_SET isn't empty the following dependency has been pulled in
##     but can be declared for certainty nonetheless:
##     * add a exec_depend tag for "message_runtime"
## * In this file (CMakeLists.txt):
##   * add "message_generation" and every package in MSG_DEP_SET to
##     find_package(catkin REQUIRED COMPONENTS ...)
##   * add "message_runtime" and every package in MSG_DEP_SET to
##     catkin_package(CATKIN_DEPENDS ...)
##   * uncomment the add_*_files sections below as needed
##     and list every .msg/.srv/.action file to be processed
##   * uncomment the generate_messages entry below
##   * add every package in MSG_DEP_SET to generate_messages(DEPENDENCIES ...)

## Generate messages in the 'msg' folder

# =============================================
# 新增内容的位置
add_message_files(
    FILES
    Person.msg
#   Message1.msg
#   Message2.msg
)
# =============================================

## Generate services in the 'srv' folder

# =============================================
# 新增内容的位置
add_service_files(
    FILES
    Add.srv
#   Service1.srv
#   Service2.srv
)
# =============================================

## Generate actions in the 'action' folder

# =======================================================
# action新增内容的位置
add_action_files(
    FILES
    DoDishes.action
#   Action1.action
#   Action2.action
)
# =======================================================

## Generate added messages and services with any dependencies listed here

# =============================================
# 新增内容的位置
generate_messages(
    DEPENDENCIES
    std_msgs
    actionlib_msgs
)
# =============================================

################################################
## Declare ROS dynamic reconfigure parameters ##
################################################

## To declare and build dynamic reconfigure parameters within this
## package, follow these steps:
## * In the file package.xml:
##   * add a build_depend and a exec_depend tag for "dynamic_reconfigure"
## * In this file (CMakeLists.txt):
##   * add "dynamic_reconfigure" to
##     find_package(catkin REQUIRED COMPONENTS ...)
##   * uncomment the "generate_dynamic_reconfigure_options" section below
##     and list every .cfg file to be processed

## Generate dynamic reconfigure parameters in the 'cfg' folder
# generate_dynamic_reconfigure_options(
#   cfg/DynReconf1.cfg
#   cfg/DynReconf2.cfg
# )

###################################
## catkin specific configuration ##
###################################
## The catkin_package macro generates cmake config files for your package
## Declare things to be passed to dependent projects
## INCLUDE_DIRS: uncomment this if your package contains header files
## LIBRARIES: libraries you create in this project that dependent projects also need
## CATKIN_DEPENDS: catkin_packages dependent projects also need
## DEPENDS: system dependencies of this project that dependent projects also need

# =============================================
# 需要新增内容的位置
catkin_package(
#  INCLUDE_DIRS include
#  LIBRARIES learning_communication
   CATKIN_DEPENDS roscpp rospy std_msgs message_runtime
#  DEPENDS system_lib
)
# =============================================

###########
## Build ##
###########

## Specify additional locations of header files
## Your package locations should be listed before other locations
include_directories(
# include
  ${catkin_INCLUDE_DIRS}
)

## Declare a C++ library
# add_library(${PROJECT_NAME}
#   src/${PROJECT_NAME}/learning_communication.cpp
# )

## Add cmake target dependencies of the library
## as an example, code may need to be generated before libraries
## either from message generation or dynamic reconfigure
# add_dependencies(${PROJECT_NAME} ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})

## Declare a C++ executable
## With catkin_make all packages are built within a single CMake context
## The recommended prefix ensures that target names across packages don't collide
# add_executable(${PROJECT_NAME}_node src/learning_communication_node.cpp)

# 新增加的链接库和依赖
add_executable(talker src/talker.cpp)
target_link_libraries(talker ${catkin_LIBRARIES})
# add_dependencies(talker ${PROJECT_NAME}_generate_messages_cpp)
add_executable(listener src/listener.cpp)
target_link_libraries(listener ${catkin_LIBRARIES})
# add_dependencies(talker ${PROJECT_NAME}_generate_messages_cpp)

# ==================================================
# 服务新增加的依赖
add_executable(server src/server.cpp)
target_link_libraries(server ${catkin_LIBRARIES})
add_dependencies(server ${PROJECT_NAME}_gencpp)

add_executable(client src/client.cpp)
target_link_libraries(client ${catkin_LIBRARIES})
add_dependencies(client ${PROJECT_NAME}_gencpp)
# ==================================================


## Rename C++ executable without prefix
## The above recommended prefix causes long target names, the following renames the
## target back to the shorter version for ease of user use
## e.g. "rosrun someones_pkg node" instead of "rosrun someones_pkg someones_pkg_node"
# set_target_properties(${PROJECT_NAME}_node PROPERTIES OUTPUT_NAME node PREFIX "")

## Add cmake target dependencies of the executable
## same as for the library above
# add_dependencies(${PROJECT_NAME}_node ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})

## Specify libraries to link a library or executable target against
# target_link_libraries(${PROJECT_NAME}_node
#   ${catkin_LIBRARIES}
# )

#############
## Install ##
#############

# all install targets should use catkin DESTINATION variables
# See http://ros.org/doc/api/catkin/html/adv_user_guide/variables.html

## Mark executable scripts (Python etc.) for installation
## in contrast to setup.py, you can choose the destination
# install(PROGRAMS
#   scripts/my_python_script
#   DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
# )

## Mark executables for installation
## See http://docs.ros.org/melodic/api/catkin/html/howto/format1/building_executables.html
# install(TARGETS ${PROJECT_NAME}_node
#   RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
# )

## Mark libraries for installation
## See http://docs.ros.org/melodic/api/catkin/html/howto/format1/building_libraries.html
# install(TARGETS ${PROJECT_NAME}
#   ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
#   LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
#   RUNTIME DESTINATION ${CATKIN_GLOBAL_BIN_DESTINATION}
# )

## Mark cpp header files for installation
# install(DIRECTORY include/${PROJECT_NAME}/
#   DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION}
#   FILES_MATCHING PATTERN "*.h"
#   PATTERN ".svn" EXCLUDE
# )

## Mark other files for installation (e.g. launch and bag files, etc.)
# install(FILES
#   # myfile1
#   # myfile2
#   DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}
# )

#############
## Testing ##
#############

## Add gtest based cpp test target and link libraries
# catkin_add_gtest(${PROJECT_NAME}-test test/test_learning_communication.cpp)
# if(TARGET ${PROJECT_NAME}-test)
#   target_link_libraries(${PROJECT_NAME}-test ${PROJECT_NAME})
# endif()

## Add folders to be run by python nosetests
# catkin_add_nosetests(test)
2.3.3 动作服务器编程实现
  • 初始化 R O S {\rm ROS} ROS节点;

  • 创建动作服务器实例;

  • 启动服务器,等待动作请求;

  • 在回调函数中完成动作功能的处理,并反馈进度信息;

  • 动作完成,发送结束信息;

  • 动作服务器编程实现:

    #include <ros/ros.h>
    #include <actionlib/server/simple_action_server.h>
    #include "learning_communication/DoDishesAction.h"
    
    typedef actionlib::SimpleActionServer<learning_communication::DoDishesAction> Server;
    
    // 收到action的goal后调用该回调函数
    void execute(const learning_communication::DoDishesGoalConstPtr& goal, Server* as)
    {
        ros::Rate r(1);
        learning_communication::DoDishesFeedback feedback;
    
        ROS_INFO("Dishwasher %d is working.", goal->dishwasher_id);
    
        // 假设洗盘子的进度,并且按照1hz的频率发布进度feedback
        for(int i=1; i<=10; i++)
        {
            feedback.percent_complete = i * 10;
            as->publishFeedback(feedback);
            r.sleep();
        }
    
        // 当action完成后,向客户端返回结果
        ROS_INFO("Dishwasher %d finish working.", goal->dishwasher_id);
        as->setSucceeded();
    }
    
    int main(int argc, char** argv)
    {
        ros::init(argc, argv, "do_dishes_server");
        ros::NodeHandle n;
    
        // 定义一个服务器
        Server server(n, "do_dishes", boost::bind(&execute, _1, &server), false);
        
        // 服务器开始运行
        server.start();
    
        ros::spin();
    
        return 0;
    }
    
2.3.4 动作客户端编程实现
  • 初始化 R O S {\rm ROS} ROS节点;

  • 创建动作客户端实例;

  • 连接动作服务端;

  • 发动动作目标;

  • 根据不同类型的服务端反馈处理回调函数;

  • 动作客户端编程实现:

    #include <actionlib/client/simple_action_client.h>
    #include "learning_communication/DoDishesAction.h"
    
    typedef actionlib::SimpleActionClient<learning_communication::DoDishesAction> Client;
    
    // 当action完成后会调用该回调函数一次
    void doneCb(const actionlib::SimpleClientGoalState& state,
            const learning_communication::DoDishesResultConstPtr& result)
    {
        ROS_INFO("Yay! The dishes are now clean");
        ros::shutdown();
    }
    
    // 当action激活后会调用该回调函数一次
    void activeCb()
    {
        ROS_INFO("Goal just went active");
    }
    
    // 收到feedback后调用该回调函数
    void feedbackCb(const learning_communication::DoDishesFeedbackConstPtr& feedback)
    {
        ROS_INFO(" percent_complete : %f ", feedback->percent_complete);
    }
    
    int main(int argc, char** argv)
    {
        ros::init(argc, argv, "do_dishes_client");
    
        // 定义一个客户端
        Client client("do_dishes", true);
    
        // 等待服务器端
        ROS_INFO("Waiting for action server to start.");
        client.waitForServer();
        ROS_INFO("Action server started, sending goal.");
    
        // 创建一个action的goal
        learning_communication::DoDishesGoal goal;
        goal.dishwasher_id = 1;
    
        // 发送action的goal给服务器端,并且设置回调函数
        client.sendGoal(goal,  &doneCb, &activeCb, &feedbackCb);
    
        ros::spin();
    
        return 0;
    }
    
2.3.5 编译代码
# CMakeLists.txt文件
# 1.设置需要编译的代码和生成的可执行文件
# 2.设置链接库;
# 3.设置依赖;
add_executable(DoDishes_client src/DoDishes_client.cpp)
target_link_libraries(DoDishes_client ${catkin_LIBRARIES})
add_dependencies(DoDishes_client ${${PROJECT_NAME}_EXPORTED_TARGETS})

add_executable(DoDishes_server src/DoDishes_server.cpp)
target_link_libraries(DoDishes_server ${catkin_LIBRARIES})
add_dependencies(DoDishes_server ${${PROJECT_NAME}_EXPORTED_TARGETS})

# 4.编译工作空间;
cd ~/willard_ws/
catkin_make

# 5.运行
roscore
rosrun learning_communication DoDishes_client
rosrun learning_communication DoDishes_server
# CMakeLists.txt文件内容

cmake_minimum_required(VERSION 2.8.3)
project(learning_communication)

## Compile as C++11, supported in ROS Kinetic and newer
# add_compile_options(-std=c++11)

## Find catkin macros and libraries
## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz)
## is used, also find other catkin packages

# =============================================
# 新增message_generation
find_package(catkin REQUIRED COMPONENTS
  roscpp
  rospy
  std_msgs
  message_generation
  # ==action新增依赖==
  actionlib_msgs
  actionlib
  # ==================
)
# =============================================

## System dependencies are found with CMake's conventions
# find_package(Boost REQUIRED COMPONENTS system)


## Uncomment this if the package has a setup.py. This macro ensures
## modules and global scripts declared therein get installed
## See http://ros.org/doc/api/catkin/html/user_guide/setup_dot_py.html
# catkin_python_setup()

################################################
## Declare ROS messages, services and actions ##
################################################

## To declare and build messages, services or actions from within this
## package, follow these steps:
## * Let MSG_DEP_SET be the set of packages whose message types you use in
##   your messages/services/actions (e.g. std_msgs, actionlib_msgs, ...).
## * In the file package.xml:
##   * add a build_depend tag for "message_generation"
##   * add a build_depend and a exec_depend tag for each package in MSG_DEP_SET
##   * If MSG_DEP_SET isn't empty the following dependency has been pulled in
##     but can be declared for certainty nonetheless:
##     * add a exec_depend tag for "message_runtime"
## * In this file (CMakeLists.txt):
##   * add "message_generation" and every package in MSG_DEP_SET to
##     find_package(catkin REQUIRED COMPONENTS ...)
##   * add "message_runtime" and every package in MSG_DEP_SET to
##     catkin_package(CATKIN_DEPENDS ...)
##   * uncomment the add_*_files sections below as needed
##     and list every .msg/.srv/.action file to be processed
##   * uncomment the generate_messages entry below
##   * add every package in MSG_DEP_SET to generate_messages(DEPENDENCIES ...)

## Generate messages in the 'msg' folder

# =============================================
# 新增内容的位置
add_message_files(
    FILES
    Person.msg
#   Message1.msg
#   Message2.msg
)
# =============================================

## Generate services in the 'srv' folder

# =============================================
# 新增内容的位置
add_service_files(
    FILES
    Add.srv
#   Service1.srv
#   Service2.srv
)
# =============================================

## Generate actions in the 'action' folder

# =======================================================
# action新增内容的位置
add_action_files(
    FILES
    DoDishes.action
#   Action1.action
#   Action2.action
)
# =======================================================

## Generate added messages and services with any dependencies listed here

# =============================================
# 新增内容的位置
generate_messages(
    DEPENDENCIES
    std_msgs
    actionlib_msgs
)
# =============================================


################################################
## Declare ROS dynamic reconfigure parameters ##
################################################

## To declare and build dynamic reconfigure parameters within this
## package, follow these steps:
## * In the file package.xml:
##   * add a build_depend and a exec_depend tag for "dynamic_reconfigure"
## * In this file (CMakeLists.txt):
##   * add "dynamic_reconfigure" to
##     find_package(catkin REQUIRED COMPONENTS ...)
##   * uncomment the "generate_dynamic_reconfigure_options" section below
##     and list every .cfg file to be processed

## Generate dynamic reconfigure parameters in the 'cfg' folder
# generate_dynamic_reconfigure_options(
#   cfg/DynReconf1.cfg
#   cfg/DynReconf2.cfg
# )

###################################
## catkin specific configuration ##
###################################
## The catkin_package macro generates cmake config files for your package
## Declare things to be passed to dependent projects
## INCLUDE_DIRS: uncomment this if your package contains header files
## LIBRARIES: libraries you create in this project that dependent projects also need
## CATKIN_DEPENDS: catkin_packages dependent projects also need
## DEPENDS: system dependencies of this project that dependent projects also need

# =============================================
# 需要新增内容的位置
catkin_package(
#  INCLUDE_DIRS include
#  LIBRARIES learning_communication
   CATKIN_DEPENDS roscpp rospy std_msgs message_runtime
#  DEPENDS system_lib
)
# =============================================

###########
## Build ##
###########

## Specify additional locations of header files
## Your package locations should be listed before other locations
include_directories(
# include
  ${catkin_INCLUDE_DIRS}
)

## Declare a C++ library
# add_library(${PROJECT_NAME}
#   src/${PROJECT_NAME}/learning_communication.cpp
# )

## Add cmake target dependencies of the library
## as an example, code may need to be generated before libraries
## either from message generation or dynamic reconfigure
# add_dependencies(${PROJECT_NAME} ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})

## Declare a C++ executable
## With catkin_make all packages are built within a single CMake context
## The recommended prefix ensures that target names across packages don't collide
# add_executable(${PROJECT_NAME}_node src/learning_communication_node.cpp)

# 新增加的链接库和依赖
add_executable(talker src/talker.cpp)
target_link_libraries(talker ${catkin_LIBRARIES})
# add_dependencies(talker ${PROJECT_NAME}_generate_messages_cpp)
add_executable(listener src/listener.cpp)
target_link_libraries(listener ${catkin_LIBRARIES})
# add_dependencies(talker ${PROJECT_NAME}_generate_messages_cpp)

# ==================================================
# 服务新增加的依赖
add_executable(server src/server.cpp)
target_link_libraries(server ${catkin_LIBRARIES})
add_dependencies(server ${PROJECT_NAME}_gencpp)

add_executable(client src/client.cpp)
target_link_libraries(client ${catkin_LIBRARIES})
add_dependencies(client ${PROJECT_NAME}_gencpp)
# ==================================================

# ======================================================================
# action新增加的依赖
add_executable(DoDishes_client src/DoDishes_client.cpp)
target_link_libraries(DoDishes_client ${catkin_LIBRARIES})
add_dependencies(DoDishes_client ${${PROJECT_NAME}_EXPORTED_TARGETS})

add_executable(DoDishes_server src/DoDishes_server.cpp)
target_link_libraries(DoDishes_server ${catkin_LIBRARIES})
add_dependencies(DoDishes_server ${${PROJECT_NAME}_EXPORTED_TARGETS})
# ======================================================================

## Rename C++ executable without prefix
## The above recommended prefix causes long target names, the following renames the
## target back to the shorter version for ease of user use
## e.g. "rosrun someones_pkg node" instead of "rosrun someones_pkg someones_pkg_node"
# set_target_properties(${PROJECT_NAME}_node PROPERTIES OUTPUT_NAME node PREFIX "")

## Add cmake target dependencies of the executable
## same as for the library above
# add_dependencies(${PROJECT_NAME}_node ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})

## Specify libraries to link a library or executable target against
# target_link_libraries(${PROJECT_NAME}_node
#   ${catkin_LIBRARIES}
# )

#############
## Install ##
#############

# all install targets should use catkin DESTINATION variables
# See http://ros.org/doc/api/catkin/html/adv_user_guide/variables.html

## Mark executable scripts (Python etc.) for installation
## in contrast to setup.py, you can choose the destination
# install(PROGRAMS
#   scripts/my_python_script
#   DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
# )

## Mark executables for installation
## See http://docs.ros.org/melodic/api/catkin/html/howto/format1/building_executables.html
# install(TARGETS ${PROJECT_NAME}_node
#   RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
# )

## Mark libraries for installation
## See http://docs.ros.org/melodic/api/catkin/html/howto/format1/building_libraries.html
# install(TARGETS ${PROJECT_NAME}
#   ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
#   LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
#   RUNTIME DESTINATION ${CATKIN_GLOBAL_BIN_DESTINATION}
# )

## Mark cpp header files for installation
# install(DIRECTORY include/${PROJECT_NAME}/
#   DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION}
#   FILES_MATCHING PATTERN "*.h"
#   PATTERN ".svn" EXCLUDE
# )

## Mark other files for installation (e.g. launch and bag files, etc.)
# install(FILES
#   # myfile1
#   # myfile2
#   DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}
# )

#############
## Testing ##
#############

## Add gtest based cpp test target and link libraries
# catkin_add_gtest(${PROJECT_NAME}-test test/test_learning_communication.cpp)
# if(TARGET ${PROJECT_NAME}-test)
#   target_link_libraries(${PROJECT_NAME}-test ${PROJECT_NAME})
# endif()

## Add folders to be run by python nosetests
# catkin_add_nosetests(test)

3.分布式通信

# 实现分布式多机通信
# 1.远程登录设置
sudo apt-get install openssh-server		# 安装ssh服务
systemctl start ssh		# 开启ssh服务
sudo ps -e | grep ssh	# 查看ssh是否开启
ping IP地址			  # 测试网络连通性 	
sudo ssh 用户名@IP地址		# 远程登录
ifconfig				# 查看ip地址

# 2.设置IP地址
# 在本地端和远程端分别设置对方的IP地址

# 本地端
sudo vim /etc/hosts
===========================================================
127.0.0.1	localhost
127.0.1.1	ros

# 增加对方的IP地址和名字
192.168.66.103 ubuntu

# The following lines are desirable for IPv6 capable hosts
::1     ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
===========================================================

# 远程端
===========================================================
127.0.0.1	localhost
127.0.1.1	ubuntu

# 增加对方的IP地址和名字
192.168.66.102 ros

# The following lines are desirable for IPv6 capable hosts
::1     ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
===========================================================

# 测试网络连通性
# 本地端
ping ubuntu

# 远程端
ping ros

# 3.从机端设置ROS_MASTER_URI
# 此处从机为hawkbot端的PC
sudo vim ~/.bashrc

==============================================
# 在~/.bashrc文件中添加内容
export ROBOT_IP=192.168.66.102	# 主机IP
export ROS_MASTER_URI=http://$ROBOT_IP:11311
==============================================

# 4.测试实例
# 4.1 启动master(主机:ros)
roscore

# 4.2 启动海龟(主机:ros)
rosrun turtlesim turtlesim_node

# 4.3 发布控制命令(从机:hawkbot)
rostopic pub -r 10 /turtle1/cmd_vel geometry_msgs/Twist "linear:
	x:2.0
	y:0.0
	z:0.0
angular:
	x:0.0
	y:0.0
	z:2.0
"

8

9

4.ROS的常用组件

4.1 Launch文件

L a u n c h {\rm Launch} Launch文件:通过 X M L {\rm XML} XML文件实现多节点的配置和启动( L a u n c h {\rm Launch} Launch可自动启动 R O S   M a s t e r {\rm ROS\ Master} ROS Master);

# 1.<launch>标签
<launch>:launch文件的根元素采用<launch>标签定义;

# 2.<node>标签
<node>:启动节点
<node pkg="package-name" type="executable-name" name="node-name"/>
参数说明:
pkg:节点所在功能包名称;
type:节点可执行文件名称;
name:节点运行时的名称;
其他参数:output、respawn、required、ns、args;

# 3.<param>标签
<param>:设置ROS系统运行中的参数,存储在参数服务器中;
<param name="output_frame" value="odom"/>
参数说明:
name:参数名;
value:参数值;

# 4.<rosparam>标签
<rosparam>:加载参数文件中的多个参数;
<rosparam file="params.yaml" command="load" ns="params"/>

# 5.<arg>标签
<arg>:launch文件内部的局部变量,仅限于launch文件使用;
<arg name="arg-name" default="arg-value"/>
参数说明:
name:参数名;
value:参数值;
调用:
<param name="foo" value="$(arg arg-name)"/>
<node name="node" pkg="package" type="type" args="$(arg arg-name)"/>

# 6.<remap>标签
<remap>:重映射ROS计算图资源的命名;
<remap from="/turtlebot/cmd_vel"to="/cmd_vel"/>
参数说明:
from:原来的名字;
to:映射后的名字;

# 7.<include>标签
<include>:包含其他launch文件;
<include file="$(dirname)/other.launch"/>
参数说明:
file:包含的其他launch文件路径;
<!-- launch文件实例,gmapping_slam.launch实例 -->

<launch>
    <node pkg="gmapping" type="slam_gmapping" name="slam_gmapping" output="screen">
        <param name="transform_publish_period" value="0.1"/>
        <param name="base_frame" value="/base_footprint"/>
        <param name="odom_frame" value="/odom"/>
        <param name="map_frame" value="/map"/>
        <param name="map_update_interval" value="2.0"/>
        <param name="maxUrange" value="8"/>
        <param name="sigma" value="0.05"/>
        <param name="kernelSize" value="1"/>
        <param name="lstep" value="0.05"/>
        <param name="astep" value="0.05"/>
        <param name="iterations" value="5"/>
        <param name="lsigma" value="0.075"/>
        <param name="ogain" value="3.0"/>
        <param name="lskip" value="0"/>
        <param name="minimumScore" value="50"/>
        <param name="srr" value="0.1"/>
        <param name="srt" value="0.2"/>
        <param name="str" value="0.1"/>
        <param name="stt" value="0.2"/>
        <param name="linearUpdate" value="1.0"/>
        <param name="angularUpdate" value="0.2"/>
        <param name="temporalUpdate" value="0.5"/>
        <param name="resampleThreshold" value="0.5"/>
        <param name="particles" value="100"/>
        <param name="xmin" value="-10.0"/>
        <param name="ymin" value="-10.0"/>
        <param name="xmax" value="10.0"/>
        <param name="ymax" value="10.0"/>
        <param name="delta" value="0.03"/>
        <param name="llsamplerange" value="0.01"/>
        <param name="llsamplestep" value="0.01"/>
        <param name="lasamplerange" value="0.005"/>
        <param name="lasamplestep" value="0.005"/>
    </node>

    <node pkg="rviz" type="rviz" name="rviz1" required="true" args="-d $(find hawkbot)/rviz/slam.rviz"/>
</launch>
4.2 TF坐标变换
4.2.1 TF坐标变换例程
sudo apt-get install ros-melodic-turtle-tf	# 注意ros版本
roslaunch turtle_tf turtle_tf_demo.launch
rosrun turtlesim turtle_teleop_key
rosrun tf view_frames		# 生成tf关系图
rosrun tf tf_echo turtle1 turtle2	# 查看具体tf关系

海龟例程坐标变换公式:
T t u r t l e 1 _ t u r t l e 2 = T t u r t l e 1 _ w o r l d ∗ T w o r l d _ t u r t l e 2 {\rm T}_{turtle1\_turtle2}={\rm T}_{turtle1\_world}*{\rm T}_{world\_turtle2} Tturtle1_turtle2=Tturtle1_worldTworld_turtle2
9

4.2.2 TF广播器和TF监听器编程实现
  1. T F {\rm TF} TF坐标变换实现步骤

    # 1.建立learning_tf功能包
    cd ~/willard_ws/src/
    catkin_create_pkg learning_tf std_msgs rospy roscpp
    
    # 2.编译功能包
    cd ~/willard_ws
    catkin_make
    source ~/willard_ws/devel/setup.bash
    
    # 3.创建tf广播器.cpp
    touch turtle_tf_broadcaster.cpp
    
    # 4.创建tf监听器.cpp
    touch turtle_tf_listener.cpp
    
    # 5.编译代码(CMakeLists.txt)
    # 设置需要编译的代码和生成的可执行文件;
    # 设置链接库;
    # ==================================================================
    add_executable(turtle_tf_broadcaster src/turtle_tf_broadcaster.cpp)
    target_link_libraries(turtle_tf_broadcaster ${catkin_LIBRARIES})
    
    add_executable(turtle_tf_listener src/turtle_tf_listener.cpp)
    target_link_libraries(turtle_tf_listener ${catkin_LIBRARIES})
    # ==================================================================
    # ======================================
    # 其他需要修改
    find_package(catkin REQUIRED COMPONENTS
      roscpp
      rospy
      std_msgs
      message_generation
      tf
    )
    # ======================================
    
    # 编译代码
    cd ~/willard_ws/
    catkin_make
    soure devel/setup.bash
    
    # 6.建立.launch文件,放置learning_tf/launch/下
    # 启动.launch文件
    roslaunch learning_tf start_demo_with_listener.launch
    
  2. T F {\rm TF} TF广播器编程实现

    • 定义 T F {\rm TF} TF广播器 ( T r a n s f o r m B r o a d c a s t e r ) ({\rm TransformBroadcaster}) (TransformBroadcaster)

    • 创建坐标变换值;

    • 发布坐标变换 ( s e n d T r a n s f o r m ) ({\rm sendTransform}) (sendTransform)

    • 编程实现:

      // turtle_tf_broadcaster.cpp文件
      #include <ros/ros.h>
      #include <tf/transform_broadcaster.h>
      #include <turtlesim/Pose.h>
      
      std::string turtle_name;
      
      void poseCallback(const turtlesim::PoseConstPtr& msg)
      {
          // tf广播器
          static tf::TransformBroadcaster br;
      
          // 根据乌龟当前的位姿,设置相对于世界坐标系的坐标变换
          tf::Transform transform;
          transform.setOrigin( tf::Vector3(msg->x, msg->y, 0.0) );
          tf::Quaternion q;
          q.setRPY(0, 0, msg->theta);
          transform.setRotation(q);
      
          // 发布坐标变换
          br.sendTransform(tf::StampedTransform(transform, ros::Time::now(), "world", turtle_name));
      }
      
      int main(int argc, char** argv)
      {
          // 初始化节点
          ros::init(argc, argv, "my_tf_broadcaster");
          if (argc != 2)
          {
              ROS_ERROR("need turtle name as argument"); 
              return -1;
          };
          turtle_name = argv[1];
      
          // 订阅乌龟的pose信息
          ros::NodeHandle node;
          ros::Subscriber sub = node.subscribe(turtle_name+"/pose", 10, &poseCallback);
      
          ros::spin();
      
          return 0;
      };
      
  3. T F {\rm TF} TF监听器编程实现

    • 定义 T F {\rm TF} TF监听器 ( T r a n s f o r m L i s t e n e r ) ({\rm TransformListener}) (TransformListener);

    • 查找坐标变换 ( w a i t F o r T r a n s f o r m 、 l o o k u p T r a n s f o r m ) ({\rm waitForTransform、lookupTransform}) (waitForTransformlookupTransform)

    • 编程实现:

      // turtle_tf_listener.cpp文件
      #include <ros/ros.h>
      #include <tf/transform_listener.h>
      #include <geometry_msgs/Twist.h>
      #include <turtlesim/Spawn.h>
      
      int main(int argc, char** argv)
      {
          // 初始化节点
          ros::init(argc, argv, "my_tf_listener");
      
          ros::NodeHandle node;
      
          // 通过服务调用,产生第二只乌龟turtle2
          ros::service::waitForService("spawn");
          ros::ServiceClient add_turtle =
          node.serviceClient<turtlesim::Spawn>("spawn");
          turtlesim::Spawn srv;
          add_turtle.call(srv);
      
          // 定义turtle2的速度控制发布器
          ros::Publisher turtle_vel =
          node.advertise<geometry_msgs::Twist>("turtle2/cmd_vel", 10);
      
          // tf监听器
          tf::TransformListener listener;
      
          ros::Rate rate(10.0);
          while (node.ok())
          {
              tf::StampedTransform transform;
              try
              {
                  // 查找turtle2与turtle1的坐标变换
                  listener.waitForTransform("/turtle2", "/turtle1", ros::Time(0), ros::Duration(3.0));
                  listener.lookupTransform("/turtle2", "/turtle1", ros::Time(0), transform);
              }
              catch (tf::TransformException &ex) 
              {
                  ROS_ERROR("%s",ex.what());
                  ros::Duration(1.0).sleep();
                  continue;
              }
      
              // 根据turtle1和turtle2之间的坐标变换,计算turtle2需要运动的线速度和角速度
              // 并发布速度控制指令,使turtle2向turtle1移动
              geometry_msgs::Twist vel_msg;
              vel_msg.angular.z = 4.0 * atan2(transform.getOrigin().y(),
                                              transform.getOrigin().x());
              vel_msg.linear.x = 0.5 * sqrt(pow(transform.getOrigin().x(), 2) +
                                            pow(transform.getOrigin().y(), 2));
              turtle_vel.publish(vel_msg);
      
              rate.sleep();
          }
          return 0;
      };
      
  4. 编译文件 ( C M a k e L i s t s . t x t ) ({\rm CMakeLists.txt}) (CMakeLists.txt)

    cmake_minimum_required(VERSION 2.8.3)
    project(learning_tf)
    
    ## Compile as C++11, supported in ROS Kinetic and newer
    # add_compile_options(-std=c++11)
    
    ## Find catkin macros and libraries
    ## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz)
    ## is used, also find other catkin packages
    
    # ===============================================
    # tf修改部分
    find_package(catkin REQUIRED COMPONENTS
      roscpp
      rospy
      std_msgs
      message_generation
      tf
    )
    # ===============================================
    
    ## System dependencies are found with CMake's conventions
    # find_package(Boost REQUIRED COMPONENTS system)
    
    
    ## Uncomment this if the package has a setup.py. This macro ensures
    ## modules and global scripts declared therein get installed
    ## See http://ros.org/doc/api/catkin/html/user_guide/setup_dot_py.html
    # catkin_python_setup()
    
    ################################################
    ## Declare ROS messages, services and actions ##
    ################################################
    
    ## To declare and build messages, services or actions from within this
    ## package, follow these steps:
    ## * Let MSG_DEP_SET be the set of packages whose message types you use in
    ##   your messages/services/actions (e.g. std_msgs, actionlib_msgs, ...).
    ## * In the file package.xml:
    ##   * add a build_depend tag for "message_generation"
    ##   * add a build_depend and a exec_depend tag for each package in MSG_DEP_SET
    ##   * If MSG_DEP_SET isn't empty the following dependency has been pulled in
    ##     but can be declared for certainty nonetheless:
    ##     * add a exec_depend tag for "message_runtime"
    ## * In this file (CMakeLists.txt):
    ##   * add "message_generation" and every package in MSG_DEP_SET to
    ##     find_package(catkin REQUIRED COMPONENTS ...)
    ##   * add "message_runtime" and every package in MSG_DEP_SET to
    ##     catkin_package(CATKIN_DEPENDS ...)
    ##   * uncomment the add_*_files sections below as needed
    ##     and list every .msg/.srv/.action file to be processed
    ##   * uncomment the generate_messages entry below
    ##   * add every package in MSG_DEP_SET to generate_messages(DEPENDENCIES ...)
    
    ## Generate messages in the 'msg' folder
    # add_message_files(
    #   FILES
    #   Message1.msg
    #   Message2.msg
    # )
    
    ## Generate services in the 'srv' folder
    # add_service_files(
    #   FILES
    #   Service1.srv
    #   Service2.srv
    # )
    
    ## Generate actions in the 'action' folder
    # add_action_files(
    #   FILES
    #   Action1.action
    #   Action2.action
    # )
    
    ## Generate added messages and services with any dependencies listed here
    # generate_messages(
    #   DEPENDENCIES
    #   std_msgs
    # )
    
    ################################################
    ## Declare ROS dynamic reconfigure parameters ##
    ################################################
    
    ## To declare and build dynamic reconfigure parameters within this
    ## package, follow these steps:
    ## * In the file package.xml:
    ##   * add a build_depend and a exec_depend tag for "dynamic_reconfigure"
    ## * In this file (CMakeLists.txt):
    ##   * add "dynamic_reconfigure" to
    ##     find_package(catkin REQUIRED COMPONENTS ...)
    ##   * uncomment the "generate_dynamic_reconfigure_options" section below
    ##     and list every .cfg file to be processed
    
    ## Generate dynamic reconfigure parameters in the 'cfg' folder
    # generate_dynamic_reconfigure_options(
    #   cfg/DynReconf1.cfg
    #   cfg/DynReconf2.cfg
    # )
    
    ###################################
    ## catkin specific configuration ##
    ###################################
    ## The catkin_package macro generates cmake config files for your package
    ## Declare things to be passed to dependent projects
    ## INCLUDE_DIRS: uncomment this if your package contains header files
    ## LIBRARIES: libraries you create in this project that dependent projects also need
    ## CATKIN_DEPENDS: catkin_packages dependent projects also need
    ## DEPENDS: system dependencies of this project that dependent projects also need
    catkin_package(
    #  INCLUDE_DIRS include
    #  LIBRARIES learning_tf
    #  CATKIN_DEPENDS roscpp rospy std_msgs
    #  DEPENDS system_lib
    )
    
    ###########
    ## Build ##
    ###########
    
    ## Specify additional locations of header files
    ## Your package locations should be listed before other locations
    include_directories(
    # include
      ${catkin_INCLUDE_DIRS}
    )
    
    ## Declare a C++ library
    # add_library(${PROJECT_NAME}
    #   src/${PROJECT_NAME}/learning_tf.cpp
    # )
    
    ## Add cmake target dependencies of the library
    ## as an example, code may need to be generated before libraries
    ## either from message generation or dynamic reconfigure
    # add_dependencies(${PROJECT_NAME} ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})
    
    ## Declare a C++ executable
    ## With catkin_make all packages are built within a single CMake context
    ## The recommended prefix ensures that target names across packages don't collide
    # add_executable(${PROJECT_NAME}_node src/learning_tf_node.cpp)
    
    ## Rename C++ executable without prefix
    ## The above recommended prefix causes long target names, the following renames the
    ## target back to the shorter version for ease of user use
    ## e.g. "rosrun someones_pkg node" instead of "rosrun someones_pkg someones_pkg_node"
    # set_target_properties(${PROJECT_NAME}_node PROPERTIES OUTPUT_NAME node PREFIX "")
    
    ## Add cmake target dependencies of the executable
    ## same as for the library above
    # add_dependencies(${PROJECT_NAME}_node ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})
    
    ## Specify libraries to link a library or executable target against
    # target_link_libraries(${PROJECT_NAME}_node
    #   ${catkin_LIBRARIES}
    # )
    
    # ======================================================================
    # tf新增内容
    add_executable(turtle_tf_broadcaster src/turtle_tf_broadcaster.cpp)
    target_link_libraries(turtle_tf_broadcaster ${catkin_LIBRARIES})
    
    add_executable(turtle_tf_listener src/turtle_tf_listener.cpp)
    target_link_libraries(turtle_tf_listener ${catkin_LIBRARIES})
    # ======================================================================
    
    #############
    ## Install ##
    #############
    
    # all install targets should use catkin DESTINATION variables
    # See http://ros.org/doc/api/catkin/html/adv_user_guide/variables.html
    
    ## Mark executable scripts (Python etc.) for installation
    ## in contrast to setup.py, you can choose the destination
    # install(PROGRAMS
    #   scripts/my_python_script
    #   DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
    # )
    
    ## Mark executables for installation
    ## See http://docs.ros.org/melodic/api/catkin/html/howto/format1/building_executables.html
    # install(TARGETS ${PROJECT_NAME}_node
    #   RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
    # )
    
    ## Mark libraries for installation
    ## See http://docs.ros.org/melodic/api/catkin/html/howto/format1/building_libraries.html
    # install(TARGETS ${PROJECT_NAME}
    #   ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
    #   LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
    #   RUNTIME DESTINATION ${CATKIN_GLOBAL_BIN_DESTINATION}
    # )
    
    ## Mark cpp header files for installation
    # install(DIRECTORY include/${PROJECT_NAME}/
    #   DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION}
    #   FILES_MATCHING PATTERN "*.h"
    #   PATTERN ".svn" EXCLUDE
    # )
    
    ## Mark other files for installation (e.g. launch and bag files, etc.)
    # install(FILES
    #   # myfile1
    #   # myfile2
    #   DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}
    # )
    
    #############
    ## Testing ##
    #############
    
    ## Add gtest based cpp test target and link libraries
    # catkin_add_gtest(${PROJECT_NAME}-test test/test_learning_tf.cpp)
    # if(TARGET ${PROJECT_NAME}-test)
    #   target_link_libraries(${PROJECT_NAME}-test ${PROJECT_NAME})
    # endif()
    
    ## Add folders to be run by python nosetests
    # catkin_add_nosetests(test)
    
  5. L a u n c h {\rm Launch} Launch文件启动

    <!-- start_demo_with_listener.launch文件 -->
    <launch>
        <!-- 海龟仿真器 -->
        <node pkg="turtlesim" type="turtlesim_node" name="sim"/>
    
        <!-- 键盘控制 -->
        <node pkg="turtlesim" type="turtle_teleop_key" name="teleop" output="screen"/>
    
        <!-- 两只海龟的tf广播 -->
        <node pkg="learning_tf" type="turtle_tf_broadcaster"
              args="/turtle1" name="turtle1_tf_broadcaster" />
        <node pkg="learning_tf" type="turtle_tf_broadcaster"
              args="/turtle2" name="turtle2_tf_broadcaster" />
    
        <!-- 监听tf广播,并且控制turtle2移动 -->
        <node pkg="learning_tf" type="turtle_tf_listener"
              name="listener" />
    
     </launch>
    
4.3 Rviz可视化平台简介
  • r v i z {\rm rviz} rviz中,可以使用可扩展标记语言 X M L {\rm XML} XML对机器人、周围物体等任何实物进行尺寸、质量、位置、材质、关节等属性的描述,且在界面中呈现出来;

  • r v i z {\rm rviz} rviz可以通过图形化的方式,实时显示机器人传感器的信息、机器人的运动状态、周围环境的变化等信息;

  • r v i z {\rm rviz} rviz可通过机器人模型参数、机器人发布的传感信息等数据,为用户进行所有可监测信息的图形化显示;用户和开发者可以在 r v i z {\rm rviz} rviz控制界面下,通过按钮、滑动条、数值等方式,控制机器人的行为;

  • r v i z {\rm rviz} rviz界面介绍:

    20

4.4 Gazebo物理仿真环境简介
  1. G a z e b o {\rm Gazebo} Gazebo简介
    • G a z e b o {\rm Gazebo} Gazebo是一款功能强大的三维物理仿真平台;
    • 具备强大的物理引擎;
    • 高质量的图形渲染;
    • 方便的编程与图形接口;
    • 开源免费;
  2. G a z e b o {\rm Gazebo} Gazebo典型应用场景
    • 测试机器人算法;
    • 机器人的设计;
    • 现实情境下的回溯测试;
  3. G a z e b o {\rm Gazebo} Gazebo主要插件
    • g a z e b o _ r o s {\rm gazebo\_ros} gazebo_ros:主要用于 g a z e b o {\rm gazebo} gazebo接口和封装、 g a z e b o {\rm gazebo} gazebo服务端和客户端的启动、 U R D F {\rm URDF} URDF模型生成等;
    • g a z e b o _ m s g s {\rm gazebo\_msgs} gazebo_msgs g a z e b o {\rm gazebo} gazebo M s g {\rm Msg} Msg S r v {\rm Srv} Srv数据结构;
    • g a z e b o _ p l u g i n s {\rm gazebo\_plugins} gazebo_plugins:用于 g a z e b o {\rm gazebo} gazebo的通用传感器插件;
    • g a z e b o _ r o s _ a p i _ p l u g i n 、 g a z e b o _ r o s _ p a t h _ p l u g i n {\rm gazebo\_ros\_api\_plugin}、{\rm gazebo\_ros\_path\_plugin} gazebo_ros_api_plugingazebo_ros_path_plugin:实现接口封装;
  4. 使用 G a z e b o {\rm Gazebo} Gazebo仿真步骤
    1. 创建仿真环境;
    2. 配置机器人模型;
    3. 开始仿真;

猜你喜欢

转载自blog.csdn.net/qq_39032096/article/details/128790168
今日推荐