ROS初学者教程(二)(官方教程精简)

1. msg 和 srv
  1. 简介
    • msg:是文本文件,描述消息的字段,自动生成不同语言的源代码;
    • srv:描述一个服务的请求与响应。

msg文件存放在软件包的msg目录下,srv文件则存放在srv目录下。msg字段可使用的类型为:

  • int8, int16, int32, int64 (以及 uint*)
  • float32, float64
  • string
  • time, duration
  • 其他msg文件
  • variable-length array[] 和 fixed-length array[C]

ROS中还有一个特殊的数据类型:Header,它含有时间戳和ROS中广泛使用的坐标帧信息。在msg文件的第一行经常可以看到Header header。

  1. msg使用流程
    2.1 创建msg
    $ roscd beginner_tutorials
    $ mkdir msg
    $ echo "int64 num" > msg/Num.msg
    
    打开package.xml确保包含以下两行:
     <build_depend>message_generation</build_depend>
     <exec_depend>message_runtime</exec_depend>
    
    打开CMakeLists.txt,找到find_package,添加message_generation依赖项,改成如下所示:
    find_package(catkin REQUIRED COMPONENTS
      roscpp
      rospy
      std_msgs
      message_generation
    )
    
    找到add_message_files代码块,改成:
    add_message_files(
     FILES
     Num.msg
    )
    

确保generate_messages()函数被调用。找到generate_messages代码块,去掉注释。
2.2 使用消息
如果rosmsg可以识别生成的消息,说明msg创建没有问题。
$ rosmsg show [message type]
rosmsg可用命令:

  rosmsg show     Show message description
  rosmsg list     List all messages
  rosmsg md5      Display message md5sum
  rosmsg package  List messages in a package
  rosmsg packages List packages that contain messages
  1. 使用srv
    3.1 创建srv
    srv文件格式类似如下:
    int64 A
    int64 B
    ---
    int64 Sum
    
    我们可以从另外一个包中复制一个srv,使用:
    $ roscp [package_name] [file_to_copy_path] [copy_path]
    $ roscp rospy_tutorials AddTwoInts.srv srv/AddTwoInts.srv
    类似于msg,srv也需要配置依赖message_generation等依赖。配置方式于上节类似。最后将add_service_files注释打开即可。
    3.2 使用rossrv
    如果srv创建成功,rossrv可以进行查看:
    $ rossrv show <service type>
2. 简单的发布与订阅

2.1. 编写发布节点

$ roscd beginner_tutorials
$ mkdir src
$ cd src

创建talker.cpp文件并粘贴以下内容:

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

#include <sstream>

int main(int argc, char **argv)
{

  ros::init(argc, argv, "talker");
  ros::NodeHandle n;
  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 msg;
    std::stringstream ss;
    ss << "hello world " << 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.2 编写订阅节点
创建listener.cpp,粘贴以下内容:

#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::init(argc, argv, "listener");

  ros::NodeHandle n;

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

  return 0;
}

2.3 构建节点
在CMakeLists.txt文件中增加以下内容:

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

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

2.4 测试
运行发布者:
$ rosrun beginner_tutorials talker
运行订阅者:
$ rosrun beginner_tutorials listener

3. 简单服务与客户端

3.1 创建srv

$ roscd beginner_tutorials
mkdir srv

创建AddTwoNum.srv文件,并粘贴以下内容:

int64 A
int64 B
---
int64 Sum

CMakeLists.txt需进行以下修改:

  1. 为find_package调用添加message_generation依赖项;
  2. 将AddTwoNum.srv加入到add_service_files项中;
  3. 打开generate_messages项

编译并用rossrv查看srv是否生成成功。
3.2 编写服务节点代码
在beginner_tutorials包中创建src/add_two_ints_server.cpp文件并粘贴以下内容进去:

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

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

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

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

  return 0;
}

3.3 编写客户端代码
在beginner_tutorials包中创建src/add_two_ints_client.cpp文件并粘贴以下内容进去:

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

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

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

  return 0;
}

3.4 构建节点
在CMakeLists.txt中新增以下内容:

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

add_executable(add_two_ints_client src/add_two_ints_client.cpp)
target_link_libraries(add_two_ints_client ${catkin_LIBRARIES})
add_dependencies(add_two_ints_client beginner_tutorials_gencpp)
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容