本节沿用之前4.3 节小海龟控制例子。
4.5.1 参数声明与设置
打开src/demo_cpp_service/src/turtle_control.cpp文件
添加测试代码
cpp
this->declare_parameter("k",1.0);
this->declare_parameter("max_speed",1.0);
this->get_parameter("k",k_);
this->get_parameter("max_speed",max_speed_);
重新构建后,运行节点
ros2 run demo_cpp_service turtle_control
查看参数列表
bohu@bohu-TM1701:~/chapt4/chapt4_ws$ ros2 param list
/turtle_controller:
k
max_speed
qos_overrides./parameter_events.publisher.depth
qos_overrides./parameter_events.publisher.durability
qos_overrides./parameter_events.publisher.history
qos_overrides./parameter_events.publisher.reliability
use_sim_time
可以看到节点声明的参数了。还可以使用rqt软件直接修改

4.5.2 接受参数事件
上面设置参数只是修改ros2参数,节点的参数值没有修改,需要增加参数设置回调函数。
修改之前的turtle_control.cpp.
cpp
#include "rclcpp/rclcpp.hpp"
#include "geometry_msgs/msg/twist.hpp"
#include "turtlesim/msg/pose.hpp"
#include "chapt4_interfaces/srv/patrol.hpp"
#include "rcl_interfaces/msg/set_parameters_result.hpp"
using Patrol = chapt4_interfaces::srv::Patrol;
using SetParametersResult = rcl_interfaces::msg::SetParametersResult;
using namespace std;
class TurtleControlNode : public rclcpp::Node
{
public:
TurtleControlNode() : Node("turtle_controller")
{
this->declare_parameter("k",1.0);
this->declare_parameter("max_speed",1.0);
this->get_parameter("k",k_);
this->get_parameter("max_speed",max_speed_);
paramter_callback_handle_ = this->add_on_set_parameters_callback(
[&](const vector<rclcpp::Parameter> ¶ms)->SetParametersResult {
for(auto param: params){
RCLCPP_INFO(this->get_logger(),"更新参数的值%s=%f",param.get_name().c_str(),param.as_double());
if(param.get_name() =="k"){
k_ = param.as_double();
}else if(param.get_name() =="max_speed"){
max_speed_ = param.as_double();
}
}
auto result = SetParametersResult();
result.successful = true;
return result;
});
patrol_service_ = this->create_service<Patrol>(
"patrol",[&](const shared_ptr<Patrol::Request> request,
shared_ptr<Patrol::Response> response) -> void {
// 判断巡逻点是否在模拟器边界内
if ((0 < request->target_x && request->target_x < 12.0f)
&& (0 < request->target_y && request->target_y < 12.0f)) {
target_x_ = request->target_x;
target_y_ = request->target_y;
response->result = Patrol::Response::SUCCESS;
}else{
response->result = Patrol::Response::FAIL;
}
});
//调用继承来父类来创建发布者
publisher_ = this->create_publisher<geometry_msgs::msg::Twist>("/turtle1/cmd_vel",10);
//订阅者
subscriber_ = this->create_subscription<turtlesim::msg::Pose>("/turtle1/pose",10,std::bind(&
TurtleControlNode::on_pose_received_,this,placeholders::_1));
}
private:
void on_pose_received_(const turtlesim::msg::Pose::SharedPtr pose) {
//1获取当前位置
auto current_x = pose->x;
auto current_y = pose->y;
RCLCPP_INFO(get_logger(),"当前:x=%f,y=%f",current_x,current_y);
//2计算与目标距离,以及当前海龟的角度差
auto distance = sqrt(
(target_x_-current_x)*(target_x_-current_x)+
(target_y_-current_y)*(target_y_-current_y)
);
auto angle = atan2((target_y_-current_y),(target_x_-current_x))-pose->theta;
//3控制策略:
auto msg = geometry_msgs::msg::Twist();
if(distance>0.1){
if(fabs(angle)>0.2)
{
msg.angular.z = fabs(angle);
}else{
msg.linear.x = k_*distance;
}
}
//4 限制最大速度
if(msg.linear.x>max_speed_){
msg.linear.x = max_speed_;
}
publisher_->publish(msg);
}
private:
OnSetParametersCallbackHandle::SharedPtr paramter_callback_handle_;
rclcpp::Service<Patrol>::SharedPtr patrol_service_;
rclcpp::Subscription<turtlesim::msg::Pose>::SharedPtr subscriber_; //订阅者智能指针
rclcpp::Publisher<geometry_msgs::msg::Twist>::SharedPtr publisher_; //发布者智能指针
double target_x_{1.0}; //目标位置X,
double target_y_{1.0}; 目标位置Y
double k_{1.0};//比例系数
double max_speed_{2.0}; //最大速度
};
int main(int argc,char *argv[])
{
rclcpp::init(argc,argv);
auto node = std::make_shared<TurtleControlNode>();
rclcpp::spin(node);
rclcpp::shutdown();
return 0;
}
主要是增加回调函数add_on_set_parameters_callback
重新构建后运行节点,打开rqt 修改属性值
bohu@bohu-TM1701:~/chapt4/chapt4_ws$ ros2 run demo_cpp_service turtle_control
INFO\] \[1736411168.111954645\] \[turtle_controller\]: 更新参数的值k=2.000000
\[INFO\] \[1736411195.539882142\] \[turtle_controller\]: 更新参数的值k=3.000000
\[INFO\] \[1736411207.634454220\] \[turtle_controller\]: 更新参数的值max_speed=2.000000
### 4.5.3 修改其他节点的参数
参数机制是基于服务通信实现的,之前python节点验证过。先看下涉及SetParameters数据类型:
bohu@bohu-TM1701:\~/chapt4/chapt4_ws$ ros2 interface show rcl_interfaces/srv/SetParameters
# A list of parameters to set.
Parameter\[\] parameters
string name
ParameterValue value
uint8 type
bool bool_value
int64 integer_value
float64 double_value
string string_value
byte\[\] byte_array_value
bool\[\] bool_array_value
int64\[\] integer_array_value
float64\[\] double_array_value
string\[\] string_array_value
---
# Indicates whether setting each parameter succeeded or not and why.
SetParametersResult\[\] results
bool successful
string reason
这也是为什么要引入相关头文件,修改后的patrol_client.cpp代码
```cpp
#include