android ros 节点编写_【ROS 学习笔记】通信机制

1. 基本概念

  • 节点(Node)
    • 一个节点就表示一个进程
    • 多节点、端到端、分布式通信机制
  • 消息(Message)
    • 节点之间通过订阅和发布传递的数据
    • 可以使用ROS提供的消息类型,也可以使用 .msg 文件自定义消息类型
  • 话题(Topic)
    • 消息通过发布/订阅(Publish/Subscribe)方式传递
    • 发布者节点(Talker)针对一个给定的话题发布消息,订阅者节点(Listener)订阅某个话题及其特定数据
    • 话题通信是【异步通信】
    • 无反馈,有缓冲,弱实时,节点关系多对多,适于数据传输
  • 服务(Service)
    • 基于服务器/客服端(Sercer/Client)模型
    • 可以使用 ROS 提供的服务类型,也可以使用 .srv 文件自定义
    • 服务通信是【同步通信】
    • 有反馈,无缓冲,强实时,节点关系一对多,适于逻辑处理
  • 节点管理器(ROS Master)
    • 统筹管理所有节点,进行节点间的查找、连接等
    • 为系统提供参数服务器,管理全局参数
    • 节点管理器也体现了ROS的弊端:ROS Master 如果 broken down,整个系统将崩溃

2. 话题通信

注:案例、代码来自胡春旭《ROS机器人开发实践》

2.1 创建 Publisher

#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 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 创建 Subscriber

#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.3 编写 CMakeLists.txt

  • CMakeLists.txt 文件是 CMake 的编译规则文件,用 catkin 命令创建功能包时会自动生产该文件,预置了一些编译选项,包含详细注释,稍作修改即可
cmake_minimum_required(VERSION 2.8.3)
project(learning_communication)

# include_directories 用于设置头文件的相对路径
# 全局路径默认为功能包的所在目录
include_directories(
  include
  ${catkin_INCLUDE_DIRS}
)

# add_executable 用于设置需要编译的代码和生产的可执行文件
# 参数1:可执行文件名称,参数2:源文件 cpp
add_executable(talker src/talker.cpp)
add_executable(listener src/listener.cpp)

# target_link_libraries 用于设置链接库(第三方库)
target_link_libraries(talker ${catkin_LIBRARIES})
target_link_libraries(listener ${catkin_LIBRARIES})

# add_dependencies 用于设置依赖
add_dependencies(talker ${PROJECT_NAME}_generate_messages_cpp)
add_dependencies(talker ${PROJECT_NAME}_generate_messages_cpp)
  • 工作空间路径下,catkin_make 进行编译
  • 编译之后,可执行文件 talkerlistener放置在工作空间 /devel/lib/<package_name>路径下

2.4 执行

roscore
rosrun <package_name> talker
rosrun <package_name> listener

2.5 自定义话题消息

(1)编写 msg 消息文件,<package_name>/msg/Person.msg

string name
uint8  sex
uint8  age

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

(2)msg 文件编译设置

  • package.xml中添加包依赖
<build_depend>message_generation</build_depend>
# 部分ROS版本,用 exec_depend 代替 run-depend
<run_depend>message_runtime</run_depend>
  • CMakeLists.txt文件中添加编译选项
# 在 find_package 中添加 message_generation
find_package(catkin REQUIRED COMPONENTS
  geometry_msgs
  roscpp
  rospy
  std_msgs
  message_generation
)  

# catkin 依赖设置
catkin_package(
#  INCLUDE_DIRS include
   CATKIN_DEPENDS geometry_msgs roscpp rospy std_msgs message_runtime
)

# 设置需要编译的 msg 文件
add_message_files(
  FILES
  Person.msg
)

generate_messages(
  DEPENDENCIES
  std_msgs
)
  • 编译后,可用如下命令进行查看
rosmsg show Person

3. 服务 Service

3.1 自定义服务数据

(1)编写 srv 文件,<package_name>/srv/AddTwoInts.srv

int64 a
int64 b
---
int64 sum

(2)srv 文件编译设置

  • package.xml 中添加包依赖(同自定义消息)
  <build_depend>message_generation</build_depend>
  <run_depend>message_runtime</run_depend>
  • CMakeLists.txt 文件中添加编译选项
# 在 find_package 中添加 message_generation
find_package(catkin REQUIRED COMPONENTS
  geometry_msgs
  roscpp
  rospy
  std_msgs
  message_generation
)  

# catkin 依赖设置
catkin_package(
#  INCLUDE_DIRS include
   CATKIN_DEPENDS geometry_msgs roscpp rospy std_msgs message_runtime
)

# 设置需要编译的 srv 文件
add_service_files(
  FILES
  AddTwoInts.srv
)

3.2 创建 Server

路径:<package_name>/src/server.cpp

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

// service回调函数,输入参数req,输出参数res
bool add(learning_communication::AddTwoInts::Request  &req,
         learning_communication::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节点初始化
    ros::init(argc, argv, "add_two_ints_server");

    // 创建节点句柄
    ros::NodeHandle n;

    // 创建一个名为add_two_ints的server,注册回调函数add()
    ros::ServiceServer service = n.advertiseService("add_two_ints", add);

    // 循环等待回调函数
    ROS_INFO("Ready to add two ints.");
    ros::spin();

    return 0;
}

3.3 创建 Client

路径:<package_name>/src/server.cpp

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

int main(int argc, char **argv)
{
    // ROS节点初始化
    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;

    // 创建一个client,请求add_two_int service
    // service消息类型是learning_communication::AddTwoInts
    ros::ServiceClient client = n.serviceClient<learning_communication::AddTwoInts>("add_two_ints");

    // 创建learning_communication::AddTwoInts类型的service消息
    learning_communication::AddTwoInts srv;
    srv.request.a = atoll(argv[1]);
    srv.request.b = atoll(argv[2]);

    // 发布service请求,等待加法运算的应答结果
    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(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)

3.5 编译运行

catkin_make

roscore
rosrun <package_name> server
rosrun <package_name> client 2 4
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值