《ROS精品入门》学习笔记三:ROS客户端

一.学习内容
本节课主要讲了一下内容:
1.ROS的topic通信模式
2.ROS的service通信模式
3. 关于CMakeList.txt
二.学习讲义
《ROS精品入门》学习笔记三:ROS客户端_第1张图片
《ROS精品入门》学习笔记三:ROS客户端_第2张图片
《ROS精品入门》学习笔记三:ROS客户端_第3张图片
三.学习笔记
1. ROS的topic通信模式
A. 这里我们自己写了一个message数据类型foo,catkin_make后生成的foo.h在目录/devel/include/turtle_move中可以看到。另外在下面源码move_subscriber.cpp的回调函数中我们看到msgs是作为shared pointers(共享指针)传递的,并且它使用到了boost库。如图:
《ROS精品入门》学习笔记三:ROS客户端_第4张图片
这里用到了C++的const变量,函数模板及shared pointer,大家需要了解下。关于boost标准库,可能很多自称熟悉C++的人甚至都不知道这个,这里推荐罗剑锋的《Boost程序库完全开发指南》。这里贴几页关于msgs共享指针处C++原理PPT:
《ROS精品入门》学习笔记三:ROS客户端_第5张图片
《ROS精品入门》学习笔记三:ROS客户端_第6张图片
B. 关于日志消息的宏ROS_INFO在下面源码注解中已注明可参考《机器人操作系统(ROS)浅析》的第4章,这是说明下这里ROS_INFO使用了C++中的定义函数宏功能,这里讲的挺好:https://onevcat.com/2014/01/black-magic-in-macro/
2. ROS的service通信模式
service跟topic是比较类似的,关于topic和service这两部分可分别参考《机器人操作系统(ROS)浅析》的第3章和第8章,书上讲的更仔细些。还是建议大家碰到一些函数的时候多点进去看一看。
3. CMakeList.txt这一块其实我也不是特别懂,对编译底层一直不太了解。
四.相关源码
1. package目录树:

turtle_move
--include
--src
   --move_publisher.cpp
   --move_subscriber.cpp
   --timer.cpp
--msg
   --foo.msg
--CMakeLists.txt
--package.xml

源码:
foo.msg:

int16 foo

move_publisher.cpp:

#include
#include

int main(int argc, char** argv)
{
    ros::init(argc, argv, "move_publisher");
    ros::NodeHandle n;
    ros::Publisher pub=n.advertise("turtle1/cmd_vel", 1000);
    geometry_msgs::Twist tw;
    tw.angular.x=0;
    tw.angular.y=0;
    tw.angular.z=2;
    tw.linear.x=2;
    tw.linear.y=0;
    tw.linear.z=0;
    ros::Rate rate(10);
    while(ros::ok()) {
        pub.publish(tw);
        ros::spinOnce();
        rate.sleep();
    }
    return 0;
}

move_subscriber.cpp:

#include<ros/ros.h>
#include<turtle_move/foo.h>

void callback(const turtle_move::foo::ConstPtr msg){  //回调函数,参数类型为一个消息的共享指针
    ROS_INFO("foo is [%d]", msg->foo);  //这里生成一条消息并发送到控制台窗口,关于“消息”详见书籍《机器人操作系统(ROS)浅析》第4章 日志消息
}

int main(int argc, char** argv){
    ros::init(argc, argv, "move_subscriber");  //初始化ROS客户端,节点默认名"move_subscriber"
    ros::NodeHandle n;  //创建节点句柄的对象,创建此对象会将你的程序注册为ROS节点管理器的节点
    ros::Subscriber sub=n.subscribe("foo_topic", 100, callback);
    //创建订阅者对象,最后一个参数指定了回调函数的地址(函数指针)
    ros::Publisher pub=n.advertise<turtle_move::foo>("foo_topic", 100);
    //发送消息的实际工作是由类名为ros::Publisher的一个对象完成的;ros::NodeHandle.advertise()为一个函数模板
    //如果你想从一个节点发布关于多个话题的消息,你需要为每个话题创建一个独立的ros::Publisher对象
    turtle_move::foo foo; //创建消息对象本身,并赋值
    foo.foo=1;
    ros::Rate rate(10);    //以赫兹为单位来控制消息发布频率
    while(ros::ok()){      //ros::ok()用于检查节点是否停止工作
        pub.publish(foo);  //发布消息
        ros::spinOnce();
        //调用此方法要求ROS去执行所有挂起的回调函数,然后然后把控制权交给我们,如果忽略ros::spinOnce会使程序表现的好像没有接收到任何消息。关于ros::spin()和ros::spinOnce()的区别详见书籍《机器人操作系统(ROS)浅析》P70
        foo.foo++;
        rate.sleep();  //调用此方法来阻止循环的迭代速率超过指定的速率
    }
    return 0;
}

timer.cpp:

#include<ros/ros.h>

void callback(const ros::TimerEvent &){
    ROS_INFO("one sec passed");
}

int main(int argc, char** argv){
    ros::init(argc, argv, "timer");
    ros::NodeHandle n;
    ros::Timer time=n.createTimer(ros::Duration(1), callback);
    ros::spin();
    return 0;
}

CMakeLists.txt:

cmake_minimum_required(VERSION 2.8.3)
project(turtle_move)

## 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
  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 run_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 run_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
    foo.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  # Or other packages containing 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 run_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 you 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 turtle_move
#  CATKIN_DEPENDS roscpp rospy
#  DEPENDS system_lib
)

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

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

## Declare a C++ library
# add_library(turtle_move
#   src/${PROJECT_NAME}/turtle_move.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(turtle_move ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})

## Declare a C++ executable
 add_executable(move_publisher src/move_publisher.cpp)
 add_executable(move_subscriber src/move_subscriber.cpp)
 add_executable(timer src/timer.cpp)

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

## Specify libraries to link a library or executable target against
 target_link_libraries(move_publisher
   ${catkin_LIBRARIES}
 )
  target_link_libraries(move_subscriber
   ${catkin_LIBRARIES}
 )
  target_link_libraries(timer
   ${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 and/or libraries for installation
# install(TARGETS turtle_move turtle_move_node
#   ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
#   LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
#   RUNTIME DESTINATION ${CATKIN_PACKAGE_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_turtle_move.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)

package.xml:


<package>
  <name>turtle_movename>
  <version>0.0.0version>
  <description>The turtle_move packagedescription>

   
  
  
  <maintainer email="[email protected]">aicrobomaintainer>


  
  
  
  <license>TODOlicense>


  
  
  
  


  
  
  
  


  
  
  
  
  
  
  
  
  
  
  
  <buildtool_depend>catkinbuildtool_depend>
  <build_depend>roscppbuild_depend>
  <build_depend>message_generationbuild_depend>
  <build_depend>rospybuild_depend>
  <run_depend>roscpprun_depend>
  <run_depend>rospyrun_depend>
  <run_depend>message_runtimerun_depend>
  <run_depend>message_generationrun_depend>

  
  <export>
    

  export>
package>

2.package目录树:

addturtle
--include
--src
   --addturtle.cpp
--CMakeLists.txt
--package.xml

源码:
addturtle.cpp:

#include
#include  //声明请求和响应的类型,每一种服务/话题 数据类型都对应一个我们必须包含的相关头文件
#include

int main(int argc, char** argv)
{
    ros::init(argc, argv, "addturtle");
    ros::NodeHandle n;
    ros::ServiceClient client=n.serviceClient("spawn");  //创建客户端对象,由这个对象完成服务端调用
    if(argc!=5) {
        ROS_INFO("usage: name theta x y");
        return 1;
    }
    turtlesim::Spawn spawn;  //创建一个请求和响应的对象
    spawn.request.name=argv[1];
    spawn.request.theta=atoll(argv[2]);
    spawn.request.x=atoll(argv[3]);
    spawn.request.y=atoll(argv[4]);
    if(client.call(spawn)){  //调用服务
        ROS_INFO_STREAM("success, spawned a turtle named " << spawn.response.name);
    }
    else{
        ROS_ERROR("FAILED TO ADD A TURTLE");
        return 1;
    }
    return 0;
}

CMakeLists.txt:

cmake_minimum_required(VERSION 2.8.3)
project(addturtle)

## 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
)

## 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 run_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 run_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  # Or other packages containing 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 run_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 you 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 addturtle
#  CATKIN_DEPENDS roscpp rospy
#  DEPENDS system_lib
)

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

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

## Declare a C++ library
# add_library(addturtle
#   src/${PROJECT_NAME}/addturtle.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(addturtle ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})

## Declare a C++ executable
 add_executable(addturtle src/addturtle.cpp)

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

## Specify libraries to link a library or executable target against
 target_link_libraries(addturtle
   ${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 and/or libraries for installation
# install(TARGETS addturtle addturtle_node
#   ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
#   LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
#   RUNTIME DESTINATION ${CATKIN_PACKAGE_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_addturtle.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)

package.xml:


<package>
  <name>addturtlename>
  <version>0.0.0version>
  <description>The addturtle packagedescription>

   
  
  
  <maintainer email="[email protected]">aicrobomaintainer>


  
  
  
  <license>TODOlicense>


  
  
  
  


  
  
  
  


  
  
  
  
  
  
  
  
  
  
  
  <buildtool_depend>catkinbuildtool_depend>
  <build_depend>roscppbuild_depend>
  <build_depend>rospybuild_depend>
  <run_depend>roscpprun_depend>
  <run_depend>rospyrun_depend>


  
  <export>
    

  export>
package>

你可能感兴趣的:(ROS,《ROS精品入门》学习笔记)