IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 人工智能 -> 04 ROS Client-Service-Server实例 -> 正文阅读

[人工智能]04 ROS Client-Service-Server实例

一、客户端 Client

  1. 初始化ROS节点
  2. 创建句柄
  3. 检测所需的服务是否存在
  4. 创建Client实例
  5. 封装要请求的数据内容
  6. 发布数据请求服务
  7. 等待Service反馈结果

1.创建源码

/*
ask the service /spawn
data type of the service is turtlesim::Spawn
*/

#include<ros/ros.h>
#include<turtlesim/Spawn.h>

int main(int argc,char **argv)
{
	//ROS INIT
	ros::init(argc,argv,"turtle_spawn");
	
	//create nodeHandle
	ros::NodeHandle node;
	
	//when /spawn service is detected
	//create a client and connect to /spawn service
	ros::service::waitForService("/spawn");
	ros::ServiceClient add_turtle = node.serviceClient<turtlesim::Spawn>("/spawn");
	
	//initialize the ask data for turtlesim::Spawn
	turtlesim::Spawn srv;
	srv.request.x = 2.0;
	srv.request.y = 2.0;
	srv.request.name = "turtle2";
	
	//ask for the service
	ROS_INFO("Call service to spawn turtle[x:0.3%f y:0.3%f name:%s]",
	srv.request.x,srv.request.y,srv.request.name.c_str());
	add_turtle.call(srv);
	
	//show the result
	ROS_INFO("Spawn turtle successfully![name:%s]",srv.response.name.c_str());
	
	return 0;
}

2.修改CMakeLists.txt

为成功编译
在build部分下添加

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

二、服务器 Server

1.编写源码

/*
This node will execuate /turtle_command
data type of the service is std_srvs/Trigger
*/

#include<ros/ros.h>
#include<geometry_msgs/Twist.h>
#include<std_srvs/Trigger.h>

//a global publisher
ros::Publisher turtle_vel_pub;

//figure out the sport statement of turtle 
//false is stop, and true is moving
bool pubCommand = false;

//Function:
//CallBack Function for service, the input parameter is req, and the output parameter is res
//when the request is called,system will execute this function
bool CommandCallBack(std_srvs::Trigger::Request &req, std_srvs::Trigger::Response &res)
{
	//not
	pubCommand = !pubCommand;
	
	//print the ask data
	ROS_INFO("Publish turtle velocity command [%s]",pubCommand==true?"YES":"NO");
	
	//set feedback data to the Client
	res.success = true;
	res.message = "Change turtle command state";
}

int main(int argc,char **argv)
{
	//ROS INIT
	ros::init(argc,argv,"turtle_command_server");
	
	//Create NodeHandle
	ros::NodeHandle n;
	
	//Create server /turtle_command
	//register the CallBack Function
	ros::ServiceServer command_service = n.advertiseService("/turtle_command",CommandCallBack);
	
	//Create a Publisher and pub the topic /turtle1_cmd_vel
	//message type is geometry_msgs::Twist
	//length of line is 10
	turtle_vel_pub=n.advertise<geometry_msgs::Twist>("/turtle1/cmd_vel",10);
	
	//waiting for the ask
	ROS_INFO("Ready to receive turtle command.");
	
	//set the rate of rotation
	ros::Rate loop_rate(10);
	
	while(ros::ok())
	{
		//check the CallBackFunction line
		ros::spinOnce();
		
		//pub the velocity command if the flag is ture
		//the main process was set in the main function
		//so the CallBackFunction will be easy
		if(pubCommand)
		{
			geometry_msgs::Twist vel_msg;
			vel_msg.linear.x=0.5;
			vel_msg.angular.z=0.2;
			turtle_vel_pub.publish(vel_msg);
		}
		
	}
}

2.修改CMakeLists.txt

为成功编译
在build部分下添加

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

3.测试

roscore
rosrun turtlesim turtlesim_node 
rosrun learning_service turtle_command_server 

执行结果:服务器准备接受service请求

[ INFO] [1647765013.874899023]: Ready to receive turtle command.

通过rosservice的call指令向服务器发起请求,内容为空(该service数据格式允许request部分为空)

rosservice call /turtle_command "{}"

该命令的反馈结果:

success: True
message: “Change turtle command state”

在服务器端结果:

[ INFO] [1647765059.771672656]: Publish turtle velocity command [YES]

海龟状态:开始画圆圈

再次执行

rosservice call /turtle_command "{}"

该命令的反馈结果:

success: True
message: “Change turtle command state”

在服务器端结果:

[ INFO] [1647765367.266284668]: Publish turtle velocity command [NO]

海龟状态:停止画圆圈

三、Service数据的定义与使用

在目录下建立srv文件夹用于存储.srv文件

1.修改Person.srv内容

string name
uint8 age
uint8 sex

uint8 unknown = 0
uint8 male= 1
uint8 female= 2
---
string result

三条横线用于划分request部分和response部分
在编译生成头文件时,两个部分将分开保存为三个头文件
Person.h PersonRequest.h PersonResponse.h

2.修改package.xml

添加消息生成、运行的功能包依赖

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

3.修改CMakeLists.txt

在find_package中添加message_generation包依赖

find_package(catkin REQUIRED COMPONENTS
  geometry_msgs
  roscpp
  rospy
  std_msgs
  turtlesim
  message_generation
)

################################################
Declare ROS messages, services and actions
################################################

部分
添加

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

无须添加Person.srv的路径,编译时会自动查找功能包下的srv文件
添加生成信息的依赖包std_msgs

4.编写Client源码

/*
This node will request service /show_person
ServiceDataType is learning_service::Person
*/

#include<ros/ros.h>
#include "learning_service/Person.h"

int main(int argc,char **argv)
{
	//ROSINIT
	ros::init(argc,argv,"person_client");
	
	//Create NodeHandle
	ros::NodeHandle n;
	
	//Searching for service /show_person 
	//Create a Client and connect it with service /show_person
	ros::service::waitForService("/show_person");
	ros::ServiceClient person_client = n.serviceClient<learning_service::Person>("/show_person");
	
	//Initialize the date which would be send to service /show_person
	learning_service::Person srv;
	srv.request.name="Herman123";
	srv.request.age=20;
	srv.request.sex=learning_service::Person::Request::male;
	
	//send request to Service /show_person
	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);
	
	//show the response
	ROS_INFO("Result:%s",srv.response.result.c_str());
	return 0;
	
}

5.编写Server源码

/*
 /show_person   server
 ServiceDataType is learning_service::Person
*/
#include<ros/ros.h>
#include"learning_service/Person.h"

//Service CALLBACKFUNCTION 
bool PersonCallBackFunction(learning_service::Person::Request &req,learning_service::Person::Response &res)
{
	//show request data
	ROS_INFO("Person name:%s age:%d sex:%d",req.name.c_str(),req.age,req.sex);
	
	//set response data
	res.result="response:OK";
	
	return true;
}

int main(int argc,char** argv)
{
	//ROSINIT
	ros::init(argc,argv,"person_server");
	
	//Create NodeHandle
	ros::NodeHandle n;
	
	//Create a server /show_person
	//register the CALLBACKFUNCTION
	//Server provide the Service /show_person
	//when server receive the request from Client
	//Server will call the CBF
	ros::ServiceServer person_service= n.advertiseService("/show_person",PersonCallBackFunction);
	
	//waiting for request and call the CBF
	ROS_INFO("READY TO SHOW PERSON INFORMATION");
	ros::spin();
	return 0;
}

6.修改CMakeLists.txt

添加依赖

add_executable(person_server src/person_server.cpp)
target_link_libraries(person_server ${catkin_LIBRARIES})
add_dependencies(person_server ${PROJECT_NAME}_gencpp)
add_executable(person_client src/person_client.cpp)
target_link_libraries(person_client ${catkin_LIBRARIES})
add_dependencies(person_client ${PROJECT_NAME}_gencpp)

7.测试

roscore

尝试调换服务器和客户端的启动顺序
当客户端先启动时,客户端无法找到服务,就会等待服务

rosrun learning_service person_client 

客户端Client反馈信息:

[ INFO] [1647790441.760583113]: waitForService: Service [/show_person]
has not been advertised, waiting…

rosrun learning_service person_server 

服务器Server提示消息:

[ INFO] [1647790528.243310236]: READY TO SHOW PERSON INFORMATION

此时客户端Client提示与反馈消息:

[ INFO] [1647790528.250326397]: waitForService: Service [/show_person]
is now available. [ INFO] [1647790528.250425869]: Call service to show
person[name:Herman123 age:20 sex:1] [ INFO] [1647790528.258398762]:
Result:response:OK

服务器Server消息:

[ INFO] [1647790528.257503152]: Person name:Herman123 age:20 sex:1

  人工智能 最新文章
2022吴恩达机器学习课程——第二课(神经网
第十五章 规则学习
FixMatch: Simplifying Semi-Supervised Le
数据挖掘Java——Kmeans算法的实现
大脑皮层的分割方法
【翻译】GPT-3是如何工作的
论文笔记:TEACHTEXT: CrossModal Generaliz
python从零学(六)
详解Python 3.x 导入(import)
【答读者问27】backtrader不支持最新版本的
上一篇文章      下一篇文章      查看所有文章
加:2022-03-21 20:50:48  更:2022-03-21 20:53:19 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 13:35:00-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码