服务通信
本节主要介绍ROS2中的服务通信,包括服务通信的基本概念,服务通信的创建,服务通信的调用,以及服务通信的示例。
【0】自定义服务消息接口
创建功能包
ros2 pkg create self_interfaces --dependencies rosidl_default_generators --license Apache-2.0
- 在
CMakeLists.txt添加
find_package(rosidl_default_generators REQUIRED)
rosidl_generate_interfaces(${PROJECT_NAME}
"srv/MyService.srv"
DEPENDENCIES xxx
)
- 在
package.xml添加
<member_of_group>rosidl_interface_packages</member_of_group>
消息接口实例-srv/MyService.srv
# Request
int32 x
int32 y
---
# Response
int32 result
【1】CPP模板
#include <rclcpp/rclcpp.hpp>
#include <self_interfaces/srv/partol.hpp>
#include <geometry_msgs/msg/twist.hpp>
#include <turtlesim/msg/pose.hpp>
class ControlNode : public rclcpp::Node
{
private:
//
rclcpp::Publisher<geometry_msgs::msg::Twist>::SharedPtr publisher_;
// 订阅者
rclcpp::Subscription<turtlesim::msg::Pose>::SharedPtr subscription_;
// 服务端
rclcpp::Service<self_interfaces::srv::Partol>::SharedPtr server_;
float target_x = {5.0}; // 普通赋值初始化
float target_y = {5.0}; // 列表初始化
void pose_callback(const turtlesim::msg::Pose::SharedPtr pose)
{
//RCLCPP_INFO(this->get_logger(),"乌龟位置:x=%.2f, y=%.2f", pose->x, pose->y);
}
void server_callback(const std::shared_ptr<self_interfaces::srv::Partol::Request> req,
std::shared_ptr<self_interfaces::srv::Partol::Response> res
)
{
if((req->target_x>0 && req->target_x<12.0) && (req->target_y>0 && req->target_y<12.0))
{
this->target_x = req->target_x;
this->target_y = req->target_y;
res->result = self_interfaces::srv::Partol::Response::SECCESS;
RCLCPP_INFO(this->get_logger(),"乌龟位置:x=%.2f, y=%.2f", this->target_x, this->target_y);
}
else
{
res->result = self_interfaces::srv::Partol::Response::FAIL;
RCLCPP_INFO(this->get_logger(),"fail");
}
}
public:
ControlNode(const std::string& node_name) : Node(node_name) //构造函数
{
publisher_ = this ->create_publisher<geometry_msgs::msg::Twist>("/turtle1/cmd_vel",10);
subscription_ = this->create_subscription<turtlesim::msg::Pose>("/turtle1/pose",10,std::bind(&ControlNode::pose_callback,this,std::placeholders::_1));
server_ = this->create_service<self_interfaces::srv::Partol>("turtle1/partol",std::bind(&ControlNode::server_callback,this,std::placeholders::_1,std::placeholders::_2));
}
};
int main(int argc, char **argv)
{
rclcpp::init(argc, argv);
/*创建对应节点的共享指针对象*/
auto node = std::make_shared<ControlNode>("ControlNode");
/* 运行节点,并检测退出信号*/
rclcpp::spin(node);
rclcpp::shutdown();
return 0;
}
【2】Python模板
import rclpy
from rclpy.node import Node
from geometry_msgs.msg import Twist
from turtlesim.msg import Pose
from self_interfaces.srv import Partol
class ControlNode(Node):
def __init__(self):
super().__init__('ControlNode')
self.publisher_ = self.create_publisher(Twist, '/turtle1/cmd_vel', 10)
self.subscription_ = self.create_subscription(Pose, '/turtle1/pose', self.pose_callback, 10)
self.server_ = self.create_service(Partol, 'turtle1/partol', self.server_callback)
self.target_x = 5.0
self.target_y = 5.0
def pose_callback(self, pose):
self.get_logger().info('乌龟位置:x=%.2f, y=%.2f' % (pose.x, pose.y))
def server_callback(self, request, response):
if (request.target_x > 0 and request.target_x < 12.0) and (request.target_y > 0 and request.target_y < 12.0):
self.target_x = request.target_x
self.target_y = request.target_y
response.result = Partol.Response.SECCESS
self.get_logger().info('乌龟位置:x=%.2f, y=%.2f' % (self.target_x, self.target_y))
else:
response.result = Partol.Response.FAIL
self.get_logger().info('fail')
return response
def main(args=None):
rclpy.init(args=args)
node = ControlNode()
rclpy.spin(node)
rclpy.shutdown()
if __name__ == '__main__':
main()
【3】参数调用与更新
// 获取参数
this->declare_parameter("k",1.0);
this->get_parameter("k",k_);
// 更新参数
this->set_parameter(rclcpp::Parameter("k",2.0));
- 引入
头文件
#include <rcl_interfaces/msg/set_parameters_result.hpp>
参数更新回调函数
rcl_interfaces::msg::SetParametersResult parameter_callback(const std::vector<rclcpp::Parameter> ¶meters)
{
rcl_interfaces::msg::SetParametersResult result;
result.successful = true;
for(const auto ¶meter : parameters)
{
if (parameter.get_name() == "k")
{
k_ = parameter.as_double();
RCLCPP_INFO(this->get_logger(),"k参数已更新为: %f", k_);
}
}
return result;
}
参数更新订阅者
OnParameterCallbackHandle::SharedPtr parameter_callback_handle_;//声明
参数更新订阅者初始化```cpp parameter_callback_handle_ = this->add_on_set_parameters_callback(std::bind(&ControlNode::parameter_callback, this, std::placeholders::_1));