Day 10 ROS Cpp Service

今天要来讲 Cpp Service 的部分,Service 是一种一问一答的通讯方式,请求的一方是客户端,提供资料的叫做服务器,在这边帮大家复习一下 Service 跟 Topic 的差异在於:

  • 讯息的传输是双向的,是会回传资讯回来的。
  • 讯息通常不会连续传输,而是在客户端请求时才传送。

Demo

今天要做的是去模拟一个客户端跟服务器互相聊天的过程。而创建的过程跟昨天类似,不熟悉的人可以去看一下昨天的,下面是待会的顺序。

  • package
  • srv
  • server.cpp
  • client.cpp
  • CMakeList.txt & package.xml

Package

首先我们需要建立一个套件包

cd ~/catkin_ws/src
catkin_create_pkg service_demo roscpp rospy std_msgs

srv

接下来要创建资料夹跟 srv档案

cd service_demo
mkdir srv
cd srv
nano Greeeting.srv

接下来一样去定义他的资料结构

string name
int32 age
---
string feedback

这边先提一下,在编译以後,他一样会自动生成几个 .hg 档, 但是因为他是 service , 所以会有全部的 Greeeting.h 、 请求的 GreeetingRequest.h 和 发送回复的 GreeetingResponse.h 。它的位置在 ~/catkin_ws/devel/include/service_demo/ 里面,我们以後要用的时候就是去 include 他。

server.cpp

在定义好通讯方式的结构後,我们要开始写服务器的部分。

//引用套件
# include <ros/ros.h>
# include <service_demo/Greeting.h>

// 定义请求处理的 function,我们定义的是 bool function ,如果正确回全 true,错误则相反
bool handle_function(service_demo::Greeting::Request &req,
					service_demo::Greeting::Response &res)
{
	// 我们直接把请求给印出来
	ROS_INFO("Request from %s with age %d ", req.name.c_str(), req.age);
	
	// 处理请求,并将结果写到 回应 里面 ,跟客户端说 嗨~
	res.feedback = "Hi " + req.name + ". I'm server!";
    // 回复正确,表示正确的完成了请求
	return true;
}

int main(int argc, char **argv)
{
	// 初始化参数,第三个参数位置是节点名称
	ros::init(argc, argv, "greetings_server");
	


    // 创建一个把手,让我们可以在後面轻松地来处理节点
	ros::NodeHandle nh;
    
    	// 定义 service 的 服务器 ,service 名称为 “greetings” ,收到请求之後把值传给handle_function 进行处理
	ros::ServiceServer service = nh.advertiseService("greetings", handle_function);
	
	// 重复查询是否要跑
	ros::spin();

	return 0;
}


client.cpp

在定义好 服务器,开始定义客户端啦

//引用套件
# include "ros/ros.h"
# include "service_demo/Greeting.h"

int main(int argc, char **argv)
{
	// 初始化参数,第三个参数位置是节点名称
	ros::init(argc, argv, "greetings_client");
	
	ros::NodeHandle nh;
    
    // 定义 服务器的 客户端,service 名字为 “greetings”,service 类型为 Service_demo
	ros::ServiceClient client = nh.serviceClient<service_demo::Greeting>("greetings");
	
//  设置 srv 请求消息的内容,这里 request 包含两个变数,name 和 age。
	srv.request.name = "HAN";
	srv.request.age = 20;
 
	if (client.call(srv))
	{
		// 注意我们请求的内容只包含一个变数 response,在接收後要级的把它转成字串    
		ROS_INFO("Response from server: %s", srv.response.feedback.c_str());
	}
	else
	{
		ROS_ERROR("Failed to call service Service_demo");
		return 1;
	}
	return 0;
}

我们可以去把 srv 里面的档案想成这样:

struct Greeting
{
    struct Request
    {
        string name;
        int age;
    }request;
    struct Response
    {
        string feedback;
    }response;
}

它里面有两个结构,一个是 Request 一个是 Response ,然後里面又各自是各自的东西。

client.call 是去跟我们的服务器去聊天,如果服务器有回他,没有以读不回,就代表成功了~

CMakeList.txt & package.xml

修改 CMakeList.txt & package.xml 的部分跟昨天是一样的,所以这边就不讲啦! 忘记的话可以去看一下昨天的部分来复习。

结语

今天就到这边了~ 明天继续看 Ros Cpp ~


<<:  Day 10 JavaScript CSS in JS

>>:  [Day12] - Django REST Framework 专案建立

Day 2 调整照片亮度

调整照片亮度 教学原文参考:调整照片亮度 这篇文章会介绍在 GIMP 使用「亮度 / 对比」、「曝光...

Program Loader

之前写了一个很简单的 Program Loader, 现在就来真正的实作它,让它能够把编译好的程序放...

DAY11: Node基础总整理

前几篇的互相比较来比较去的,是不是都有点乱了思绪,今天来做个小复习,从DAY5: node 的内部机...

Day27 - 动态模型 part2 (LSTM with attention)

回顾一下昨天提到的,我们希望透过将 attention 机制加到 LSTM 中藉此找出每段语音中重要...

【DAY 20】数据分析没有这麽难,透过 Microsoft Power BI ,让你事半功倍!(更多共享 Power BI 仪表板技巧)

哈罗大家好~ 昨天我们初步了解如何制作一个简单的 Power BI 视觉化报表,让我们可以针对想要了...