上节课我们说到了客户端请求服务,然后服务端提供服务,这节课我们就来说说服务端是如何实现提供服务的。
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,输出参数res
bool 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区域下,添加如下内容
xxxxxxxxxx
add_executable(turtle_vel_command_server src/turtle_vel_command_server.cpp)
target_link_libraries(turtle_vel_command_server ${catkin_LIBRARIES})
3)、工作空间目录下编译代码
xxxxxxxxxx
cd ~/catkin_ws
catkin_make
source devel/setup.bash #需要配置环境变量,否则系统无法找到运行程序
4)、运行程序
xxxxxxxxxx
roscore
rosrun turtlesim turtlesim_node
rosrun 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 rospy
import thread,time
from geometry_msgs.msg import Twist
from 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)、运行程序
xxxxxxxxxx
roscore
rosrun turtlesim turtlesim_node
rosrun learning_server turtle_vel_command_server.py
3)、程序运行效果和程序说明与C++实现的效果一致。