ros---服务端和客户端

服务模型:

想对于发布订阅模型的区别:请求一次才会接收一次,而不是不断的发布。

自定义服务数据

1.定义srv文件

2.在package.xml中添加功能包依赖

<build_depend>message_generation</build_depend>
<exec_depend>message_runtime</exec_depend>

3.在CMakeLists.txt添加编译选项

add_service_files(FILES Person.srv)
generate_messages(DEPENDENCIES std_msgs)

4.编译生成语言的相关文件

第一个.h文件是后两个的集合,前面的PersonRequest.h是“---”上面的,Person Response.h是“---”下面的。

添加到cMakeLists.txt

客户端:

/**
 * 该例程将请求/show_person服务,服务数据类型learning_service::Person
 */

#include <ros/ros.h>
#include "learning_service/Person.h"   //头文件包含,这里包含的是刚动态生成的头文件

int main(int argc, char** argv)
{
    // 初始化ROS节点
	ros::init(argc, argv, "person_client");

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

    // 发现/show_person服务后,创建一个服务客户端,连接名为/show_person的service
    //waitForService,等待这个show_person这样一个服务的提供者运行起来
	ros::service::waitForService("/show_person");
	ros::ServiceClient person_client = node.serviceClient<learning_service::Person>("/show_person");
	//在这里创建Client这一端,Client这一端会去发布的请求数据是learning_service::Person(自定义的),另外其数据的service的对象是要用的show_person通道
	
    // 初始化learning_service::Person的请求数据
    //针对person数据添加进来名字年龄性别,这里与之前的使用方法完全一样
	learning_service::Person srv;
	srv.request.name = "Tom";
	srv.request.age  = 20;
	srv.request.sex  = learning_service::Person::Request::male;
	//因为之前定义的宏,所以male的定义可以用learning_service::Person因为是在request里面,所以与message的区别是新加了一个request命名空间

    // 请求服务调用
    //接下来通过person_client发布一个call去请求把该请求数据发出去,然后回卡在这里等待srv的反馈结果最终反馈收到之后会跳到最后一行显示反馈的结果
	ROS_INFO("Call service to show person[name:%s, age:%d, sex:%d]", 
			 srv.request.name.c_str(), srv.request.age, srv.request.sex);

	person_client.call(srv);

	// 显示服务调用结果
	ROS_INFO("Show person result : %s", srv.response.result.c_str());

	return 0;
};
//要注意learning_service::Person的使用方式,要include头文件,然后置于尖括号里,之后填充具体数据,使用起来就是learning_service的具体空间加上Person名字learning_service::Person srv注意这里的Person名字与定义的srv的文件名Person srv是一样的,因为我们生成头文件的时候头文件的命名就会完全根据这个文件的名字来命名
//这就是我们在Client这一端使用person数据类型的方式

 服务端

/**
 * 该例程将执行/show_person服务,服务数据类型learning_service::Person
 */
 
#include <ros/ros.h>
#include "learning_service/Person.h" 
//一样先调用include头文件

// service回调函数,输入参数req,输出参数res
bool personCallback(learning_service::Person::Request  &req,
         			learning_service::Person::Response &res)
{
    // 显示请求数据,人的名字年龄性别
    ROS_INFO("Person: name:%s  age:%d  sex:%d", req.name.c_str(), req.age, req.sex);

	// 设置反馈数据,ok可以改,因为这是一个字符串反馈给Client客户端的,比如OK,success都可以
	res.result = "OK";

    return true;
}

int main(int argc, char **argv)
{
    // ROS节点初始化
    ros::init(argc, argv, "person_server");

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

    // 创建一个名为/show_person的server,注册回调函数personCallback
    //创建一个server的实例,server这边会一直在提供show_person这样一个server服务,然后一旦有服务请求进来之后调用personCallback进入到回调函数
    ros::ServiceServer person_service = n.advertiseService("/show_person", personCallback);

    // 循环等待回调函数
    ROS_INFO("Ready to show person informtion.");
    ros::spin();
    //最终有一个spin,会不断的等待request数据进来,一旦有request进来之后就会进入到回调函数里来,所以我们的server端是一个循环,会一直在spin里执行,我们的Client端request一次之后会结束,我们可以不断的去运行这个Client这端的程序,server这端只用运行一次就可以
 
    return 0;
}
//在这里我们需要注意定义好的Person,先包含头文件然后可以去使用,同时注意回调函数里的输入参数,一般都是这样的类型,前面learning_service::Person然后Request端和Response端,这两个命名空间是ROS强制定义的,只需要修改前面这段learning_service::Person就可以改成所定义的数据类型;还有后面数据类型的使用方式 req.name.c_str(), req.age, req.sex
//这就是我们自定义的数据在person的server端的使用的方式
  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
ROS系统中,服务端客户端的概念可以理解为提供服务和请求服务的节点服务端节点提供服务,客户端节点请求服务,它们之间通过消息传递进行通信。 下面是一个简单的服务端客户端的Python编程示例: 服务端代码: ```python #!/usr/bin/env python import rospy from std_srvs.srv import Empty def my_service_callback(request): print("My service has been called!") #实现服务功能 return [] rospy.init_node('my_service_server') my_service = rospy.Service('/my_service', Empty, my_service_callback) print("My service is ready to receive requests!") rospy.spin() #保持节点运行状态 ``` 客户端代码: ```python #!/usr/bin/env python import rospy from std_srvs.srv import Empty rospy.init_node('my_service_client') rospy.wait_for_service('/my_service') #等待服务启动 my_service_proxy = rospy.ServiceProxy('/my_service', Empty) response = my_service_proxy() #发送请求 ``` 上述代码中,服务端使用`rospy.Service`函数创建一个服务节点,指定服务名称为`/my_service`,服务类型为`Empty`,并指定回调函数`my_service_callback`用于处理服务请求。 客户端使用`rospy.ServiceProxy`函数创建一个服务代理,指定服务名称为`/my_service`,服务类型为`Empty`,并通过调用`my_service_proxy()`方法发送请求,最终获得服务的响应结果。 需要注意的是,服务端客户端节点名称应该相互独立,避免节点名称冲突。同时,在ROS系统中,服务端客户端节点的启动顺序也很重要,需要确保服务端节点客户端节点之前启动。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

夜路难行々

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值