ROS基础(四):客户端client的编程实现&服务端Server的编程实现

学习ROS基础的电子笔记,摘录自各类ROS基础课程,文末会附上本次内容参考的相关课程视频链接。

(一)客户端client的编程实现

这次课程主要实现通过/spawn话题实现服务端与客户端的通讯,其中客户端Client发送request请求给服务端,其消息格式为turtlesim::Span,即turtlesim包中定义的Span数据结构,并且接收Server端回复的Request。

1. 创建新的功能包

cd ~/catkin_ws/src
catkin_create_pkg learning_service roscpp rospy geometry_msgs turtlesim

2. 编写turtle_spawn.cpp文件

vim ~/catkin_ws/src/learning_service/src/turtle_spawn.cpp
/**
 *该例程将请求/spawn服务,服务数据类型turtlesim::Spawn
 */

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

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

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

        // 发现/spawn服务后,创建一个服务客户端,连接名为/spawn的service
        ros :: service :: waitForService("/spawn") ;
        ros :: ServiceClient add_turtle = n.serviceClient<turtlesim :: Spawn>("/spawn") ;

        // 初始化turtle::Spawn的请求数据
        turtlesim :: Spawn srv ;
        srv.request.x = 2.0 ;
        srv.request.y = 2.0 ;
        srv.request.name = "turtle2" ;

        // 请求服务调用
        ROS_INFO("Call service to spawn turtle[x: %0.6f, y: %0.6f, name:%s]", srv.request.x, srv.request.y, srv.request.name.c_str()) ;

        add_turtle.call(srv) ;

        // 显示服务调用结果
        ROS_INFO("Spawn turtle successfully [name: %s]", srv.response.name.c_str()) ;

         return 0 ;
}

call()是一个阻塞型函数,直到得到反馈,才会有下一步反应。

3. 修改编译文件并编译

vim ~/catkin_ws/src/learning_service/CMakeLists.txt

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

cd ~/catkin_ws
catkin_make

4. 执行client

// terminal1
roscore

//terminal2
rosrun turtlesim turtlesim_node

// terminal3
cd ~/catkin_ws
source devel/setup.bash
rosrun learning_topic turtle_spawn

运行结果如下图:
在这里插入图片描述

(二)服务端Server的编程实现

client主要负责请求海龟是否运动,Server主要接收海龟是否运动的请求,并通过topic发送速度的指令来响应client的运动请求。所以这一节除了完成server端的代码,还需要实现一个新的话题.turtle_command。关于client的request,通过数据结构为std_srvs::Trigger实现。关于service的运动速度控制响应,通过发布新话题/turtle1/cmd_vel实现,其信息类型为geometry_msgs::Twist。

1. 编写turtle_command_server.cpp

vim ~/catkin_ws/src/learning_service/src/turtle_command_server.cpp

/**
 *该例程将执行/turtle_command服务,服务数据类型std_srvs/Trigger
 */

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

ros :: Publisher turtle_vel_pub ;
bool pubCommand = false ;

// Service回调函数,输入参数req, 输出参数res
bool commandCallback(std_srvs :: Trigger :: Request &req,
                std_srvs :: Trigger :: Response &res){

        pubCommand = !pubCommand ;

        // 显示请求数据, 当有请求唤醒commandCallback函数时,会改变现在pubcomman>的状态,即乌龟会改变现在的运动状态(运动/静止);
        ROS_INFO("Publish turtle velocity command [%s]", pubCommand == true ? "yes" : "No") ;
         // 设置反馈数据
        res.success = true ;
        res.message = "Change turtle command status!" ;

        return true ;
}

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

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

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

        // 创建一个publisher,发布名为/turtle1/cmd_vel的topic,消息类型为geometry_msgs :: Twist,队列长度为10
        turtle_vel_pub = n.advertise<geometry_msgs :: Twist>("/turtle1/cmd_vel", 10) ;

        // 循环等待回调函数
        ROS_INFO("Ready to receive turtle command") 

        // 设置循环频率
        ros :: Rate loop_rate(10) ;

        while(ros :: ok()) {
                // 查看一次回调函数队列
                ros :: spinOnce() ;

                // 如果标志pubCommand为true,则发布速度指令
                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) ;
                }

                // 按照循环频率延时
                loop_rate.sleep() ;
        }

        return 0 ;
}

我们可以通过

rossrv show std_srvs/Trigger

命令来查看Trigger的数据格式

bool success
string message

2.修改编译文件并编译

vim ~/catkin_ws/src/learning_service/CMakeLists.txt

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

// ESC+:wq保存退出后完成编译
cd ~/catkin_ws
catkin_make

3. 执行server

// terminal1
roscore

// terminal2
rosrun turtlesim turtlesim_node

// terminal3
cd ~/catkin_ws
source devel/setup.bash
rosrun learning_service turtle_command_server

//terminal4,模拟客户端请求的情况
rosservice call /turtle_command "{}"

"{}的理解:Trigger数据格式的请求的message是空的,所以在{}中没有内容,这里可以用tap快捷键补全,实现效果如下。
在这里插入图片描述
当再次从client端发送request时,海龟停止运动,如图:
在这里插入图片描述

参考课程: ROS入门21讲(古月居-第13讲&第14讲)

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值