ROS通信

1.话题通信
话题通信是ROS中使用频率最高的一种通信模式,话题通信是基于发布订阅模式的,也即:一个节点发布消息,另一个节点订阅该消息。
用于不断更新的、少逻辑处理的数据传输场景。
ROS Master (管理者)
Talker (发布者)
Listener (订阅者)
ROS Master 负责保管 Talker 和 Listener 注册的信息,并匹配话题相同的 Talker 与 Listener,帮助 Talker 与 Listener 建立连接,连接建立后,Talker 可以发布消息,且发布的消息会被 Listener 订阅。
上述实现流程中,RPC协议,TCP协议
(发布者)
int main(int argc, char* argv[])
{
    setlocale(LC_ALL, "");
    ros::init(argc, argv, "pub");//初始化ROS节点,命名唯一
    ros::NodeHandle nh;//实例化ROS句柄
    ros::Publisher pub = nh.advertise<std_msgs::String>("hellotopic", 10);//实例化发布者对象,第3参数为true时保留最后的msg
    std_msgs::String msg;
    ros::Rate rate(5);//5Hz
    int count = 0;
    ROS_INFO("pub start");
    while(ros::ok())
    {
        ++count;
        std::stringstream ss;
        ss << "hello --- " << count;
        msg.data = ss.str();
        pub.publish(msg);//发布消息
        ROS_INFO("pub data: %s", ss.str().c_str());
        rate.sleep();//5Hz, 0.2s
        ros::spinOnce();//处理回调
    }
    ROS_INFO("pub end");
    return 0;
}
(订阅者)
void doMsg(const std_msgs::StringConstPtr &msgptr)//处理订阅消息回调
{
    ROS_INFO("sub data: %s", msgptr->data.c_str());
}
int main(int argc, char *argv[])
{
    setlocale(LC_ALL, "");
    ros::init(argc, argv, "sub");//初始化ROS节点,命名唯一
    ros::NodeHandle nh;//实例化ROS句柄
    ros::Subscriber sub = nh.subscribe("hellotopic", 10, doMsg);//实例化订阅者对象
    ros::spin();//处理回调
    return 0;
}
自定义消息类型
功能包下新建 msg 目录,添加文件 Person.msg
package.xml中添加编译依赖与执行依赖
  <build_depend>message_generation</build_depend>
  <exec_depend>message_runtime</exec_depend>
CMakeLists.txt编辑 msg 相关配置
find_package(catkin REQUIRED COMPONENTS
  roscpp
  rospy
  std_msgs
  message_generation #需要加入 message_generation,必须有 std_msgs
)
# 配置 msg 源文件
add_message_files(
  FILES
  Person.msg
)
# 生成消息时依赖于 std_msgs
generate_messages(
  DEPENDENCIES
  std_msgs
)
#执行时依赖
catkin_package(
#  INCLUDE_DIRS include
#  LIBRARIES demo02_talker_listener
  CATKIN_DEPENDS roscpp rospy std_msgs message_runtime
#  DEPENDS system_lib
)
#配置原文件多加一个
add_dependencies(person_talker ${PROJECT_NAME}_generate_messages_cpp)
add_dependencies(person_listener ${PROJECT_NAME}_generate_messages_cpp)

2.服务通信
服务通信也是ROS中一种极其常用的通信模式,服务通信是基于请求响应模式的,是一种应答机制。也即: 一个节点A向另一个节点B发送请求,B接收处理请求并产生响应结果返回给A。
用于偶然的、对实时性有要求、有一定逻辑处理需求的数据传输场景。
ROS master(管理者)
Server(服务端)
Client(客户端)
ROS Master 负责保管 Server 和 Client 注册的信息,并匹配话题相同的 Server 与 Client ,帮助 Server 与 Client 建立连接,连接建立后,Client 发送请求信息,Server 返回响应信息。
ROS Master 会根据注册表中的信息匹配Server和 Client,并通过 RPC 向 Client 发送 Server 的 TCP 地址信息。
服务通信中,数据分成两部分,请求与响应,在 srv 文件中请求和响应使用---分割,具体实现如下,功能包下新建 srv 目录,添加 xxx.srv 文件
package.xml中添加编译依赖与执行依赖
  <build_depend>message_generation</build_depend>
  <exec_depend>message_runtime</exec_depend>
CMakeLists.txt编辑 srv 相关配置
find_package(catkin REQUIRED COMPONENTS
  roscpp
  rospy
  std_msgs
  message_generation
)
add_service_files(
  FILES
  AddInts.srv
)
generate_messages(
  DEPENDENCIES
  std_msgs
)
#执行时依赖
catkin_package(
#  INCLUDE_DIRS include
#  LIBRARIES demo02_talker_listener
  CATKIN_DEPENDS roscpp rospy std_msgs message_runtime
#  DEPENDS system_lib
)
#配置原文件多加一个
add_dependencies(AddInts_Server ${PROJECT_NAME}_gencpp)
add_dependencies(AddInts_Client ${PROJECT_NAME}_gencpp)
(服务端)
bool doaddints(plumb_server_client::addintsRequest &request, 
plumb_server_client::addintsResponse &response)
{
    int num1 = request.num1;
    int num2 = request.num2;
    int sum = num1 + num2;
    response.sum = sum;
    ROS_INFO("请求数据: num1 = %d, num2 = %d", num1, num2);
    ROS_INFO("结果: sum = %d", sum);
    return true;
}
int main(int argc, char *argv[])
{
    setlocale(LC_ALL, "");
    ROS_INFO("sever start");
    ros::init(argc, argv, "sever");
    ros::NodeHandle nh;
    ros::ServiceServer sever = nh.advertiseService("addints", doaddints);
    ros::spin();
    ROS_INFO("sever end");
    return 0;
}
(客户端)
int main(int argc, char *argv[])
{
    setlocale(LC_ALL, "");
    ROS_INFO("client start");
    ros::init(argc, argv, "client");
    ros::NodeHandle nh;
    ros::ServiceClient client = nh.serviceClient<plumb_server_client::addints>("addints");
    plumb_server_client::addints ai;
    ai.request.num1 = 100;
    ai.request.num2 = 200;
    bool ret = client.call(ai);
    if(ret)
    {
        ROS_INFO("request success\nsum = %d", ai.response.sum);
    }
    else
    {
        ROS_INFO("request error");
    }
    ROS_INFO("client end");
    return 0;
}
在客户端发送请求前添加:client.waitForExistence();或:ros::service::waitForService("AddInts");这是一个阻塞式函数,只有服务启动成功后才会继续执行

3.参数服务器
参数服务器在ROS中主要用于实现不同节点之间的数据共享。参数服务器相当于是独立于所有节点的一个公共容器,可以将数据存储在该容器中,被不同的节点调用,当然不同的节点也可以往其中存储数据。
ROS Master (管理者)
Talker (参数设置者)
Listener (参数调用者)
ROS Master 作为一个公共容器保存参数,Talker 可以向容器中设置参数,Listener 可以获取参数。
存储一些多节点共享的数据,类似于全局变量。
注意:参数服务器不是为高性能而设计的,因此最好用于存储静态的非二进制的简单数据
//增(2方案)
    nh.setParam("type", "xiaohuang");
    nh.setParam("radius", 0.15);
    ros::param::set("type_param", "xiaobai");
    ros::param::set("radius_param", 0.15);
//改(2方案)
    nh.setParam("radius", 0.2);
    ros::param::set("radius_param", 0.25);
//查(3方案)
    double radius = nh.param("radius", 0.0);
    bool ret = nh.getParam("radius", radius2);
    bool ret2 = nh.getParamCached("radius", radius3);//(性能上有提升)
//查询键
    nh.getParamNames(names);
    nh.hasParam("radius");
    nh.searchParam("radius", key);
//删除(2方案)
    bool ret = nh.deleteParam("radius");
    bool ret2 = ros::param::del("radius_param");

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值