上节课我们说到了客户端请求服务,然后服务端提供服务,这节课我们就来说说服务端是如何实现提供服务的。
1)、初始化ROS节点
2)、创建Server实例
3)、循环等待服务请求,进入回调函数
4)、在回调函数中完成服务的功能处理,并且反馈应答数据
turtle_vel_command_server.cpp
x/** * 该例程将执行/turtle_vel_command服务,服务数据类型std_srvs/Trigger */
ros::Publisher turtle_vel_pub;bool pubvel = false;
// service回调函数,输入参数req,输出参数resbool pubvelCallback(std_srvs::Trigger::Request &req, std_srvs::Trigger::Response &res){ pubvel = !pubvel;
ROS_INFO("Do you want to publish the vel?: [%s]", pubvel==true?"Yes":"No");// 打印客户端请求数据
// 设置反馈数据 res.success = true; res.message = "The status is changed!";
return true;}
int main(int argc, char **argv){ ros::init(argc, argv, "turtle_vel_command_server");
ros::NodeHandle n;
// 创建一个名为/turtle_vel_command的server,注册回调函数pubvelCallback ros::ServiceServer command_service = n.advertiseService("/turtle_vel_command", pubvelCallback);
// 创建一个Publisher,发布名为/turtle1/cmd_vel的topic,消息类型为geometry_msgs::Twist,队列长度8 turtle_vel_pub = n.advertise<geometry_msgs::Twist>("/turtle1/cmd_vel", 8);
ros::Rate loop_rate(10);// 设置循环的频率
while(ros::ok()) { ros::spinOnce();// 查看一次回调函数队列 // 判断pubvel为True,则发布小海龟速度指令 if(pubvel) { geometry_msgs::Twist vel_msg; vel_msg.linear.x = 0.6; vel_msg.angular.z = 0.8; turtle_vel_pub.publish(vel_msg); }
loop_rate.sleep();//按照循环频率延时 }
return 0;}1)、程序流程图

2)、在CMakelist.txt中配置,build区域下,添加如下内容
xxxxxxxxxxadd_executable(turtle_vel_command_server src/turtle_vel_command_server.cpp)target_link_libraries(turtle_vel_command_server ${catkin_LIBRARIES})
3)、工作空间目录下编译代码
xxxxxxxxxxcd ~/catkin_wscatkin_makesource devel/setup.bash #需要配置环境变量,否则系统无法找到运行程序
4)、运行程序
xxxxxxxxxxroscorerosrun turtlesim turtlesim_noderosrun learning_server turtle_vel_command_server
5)、运行效果截图

6)、程序说明
首先,运行小海龟这个节点后,可以在终端输入rosservice list,查看当前的服务有哪些,结果如下

然后,我们再运行turtle_vel_command_server程序,再输入rosservice list,会发现多了个turtle_vel_command_server,如下图所示

然后,我们通过在终端输入rosservice call /turtle_vel_command_server调用这个服务,会发现小海龟做圆周运动,再次调用服务的话,小海龟停止了运动。这是因为在服务回调函数里边,我们把pubvel的值做了反转,然后反馈回去,主函数就会判断pubvel的值,如果是True就发布速度指令,为False则不发布指令。
turtle_vel_command_server.py
xxxxxxxxxx#!/usr/bin/env python# -*- coding: utf-8 -*-# 该例程将执行/turtle_command服务,服务数据类型std_srvs/Trigger
import rospyimport thread,timefrom geometry_msgs.msg import Twistfrom std_srvs.srv import Trigger, TriggerResponse
pubvel = False;turtle_vel_pub = rospy.Publisher('/turtle1/cmd_vel', Twist, queue_size=8)
def pubvel_thread(): while True: if pubvel: vel_msg = Twist() vel_msg.linear.x = 0.6 vel_msg.angular.z = 0.8 turtle_vel_pub.publish(vel_msg) time.sleep(0.1)
def pubvelCallback(req): global pubvel
pubvel = bool(1-pubvel)
rospy.loginfo("Do you want to publish the vel?[%s]", pubvel)# 显示请求数据
return TriggerResponse(1, "Change state!")# 反馈数据
def turtle_pubvel_command_server(): rospy.init_node('turtle_vel_command_server')# ROS节点初始化
# 创建一个名为/turtle_command的server,注册回调函数pubvelCallback s = rospy.Service('/turtle_vel_command', Trigger, pubvelCallback)
# 循环等待回调函数 print "Ready to receive turtle_pub_vel_command."
thread.start_new_thread(pubvel_thread, ()) rospy.spin()
if __name__ == "__main__": turtle_pubvel_command_server()1)、程序流程图

2)、运行程序
xxxxxxxxxxroscorerosrun turtlesim turtlesim_noderosrun learning_server turtle_vel_command_server.py
3)、程序运行效果和程序说明与C++实现的效果一致。