前言
通常,一个节点需要对其自身参数或另一个节点的参数的更改做出响应。ParameterEventHandler类使监听参数更改变得容易,这样代码就可以对它们做出响应。
动动手
创建一个包
进入工作空间根路径的src下(ros2_ws/src),创建名为ParameterEventHandler的功能包:
$ros2 pkg create --build-type ament_cmake --license Apache-2.0 cpp_parameter_event_handler --dependencies rclcpp
如有需要可再更新下package.xml的一些信息(最好还是养成一种更新的习惯):
<description>C++ parameter events client tutorial</description>
<maintainer email="you@email.com">Your Name</maintainer>
<license>Apache License 2.0</license>
码个码
在刚创建的功能包ParameterEventHandler的src路径下创建parameter_event_handler.cpp,将下面C++代码复制进去:
#include <memory>
#include "rclcpp/rclcpp.hpp"
class SampleNodeWithParameters : public rclcpp::Node
{
public:
SampleNodeWithParameters()
: Node("node_with_parameters")
{
this->declare_parameter("an_int_param", 0);
// Create a parameter subscriber that can be used to monitor parameter changes
// (for this node's parameters as well as other nodes' parameters)
param_subscriber_ = std::make_shared<rclcpp::ParameterEventHandler>(this);
// Set a callback for this node's integer parameter, "an_int_param"
auto cb = [this](const rclcpp::Parameter & p) {
RCLCPP_INFO(
this->get_logger(), "cb: Received an update to parameter \"%s\" of type %s: \"%ld\"",
p.get_name().c_str(),
p.get_type_name().c_str(),
p.as_int());
};
cb_handle_ = param_subscriber_->add_parameter_callback("an_int_param", cb);
}
private:
std::shared_ptr<rclcpp::ParameterEventHandler> param_subscriber_;
std::shared_ptr<rclcpp::ParameterCallbackHandle> cb_handle_;
};
int main(int argc, char ** argv)
{
rclcpp::init(argc, argv);
rclcpp::spin(std::make_shared<SampleNodeWithParameters>());
rclcpp::shutdown();
return 0;
}
代码解释
头文件#include<memory>,以使代码可以使用std::make_shared模板。接下来,#include“rclcpp/crccpp.hpp”,以允许代码引用rclcpp接口提供的各种功能,包括ParameterEventHandler类。
在类声明之后,代码定义了一个类SampleNodeWithParameters。该类的构造函数声明一个整数参数an_int_param,默认值为0。接下来,该代码创建一个ParameterEventHandler,用于监视参数的更改。最后,该代码创建一个lambda函数,并将其设置为每当更新_int_param时要调用的回调。
在类声明之后,代码定义了一个类SampleNodeWithParameters。该类的构造函数声明一个整数参数an_int_param,默认值为0。接下来,该代码创建一个ParameterEventHandler,用于监视参数的更改。最后,该代码创建一个lambda函数,并将其设置为每当更新_int_param时要调用的回调。
修改CMakeLists.txt
将下面内容复制到find_package(rclcpp REQUIRED)
之后:
add_executable(parameter_event_handler src/parameter_event_handler.cpp)
ament_target_dependencies(parameter_event_handler rclcpp)
install(TARGETS
parameter_event_handler
DESTINATION lib/${PROJECT_NAME}
)
构建运行
首先依然是最好检查下依赖,进入工作空间根路径下:
$rosdep install -i --from-path src --rosdistro $ROS_DISTRO -y
构建一下:
$colcon build --packages-select cpp_parameter_event_handler
在新的终端source下环境:
$source install/setup.bash
开始运行:
$ros2 run cpp_parameter_event_handler parameter_event_handler
我们打开另外一个终端,source环境,并运行下面修改参数的命令,看看parameter_event_handler终端会打印出什么内容:
$ros2 param set node_with_parameters an_int_param 43
监视另一个节点参数更改事件
我们来修改下SampleNodeWithParameters类的构造函数,添加一个回调函数,实现对另外一个节点参数改变事件的监视。我们将使用parameter_blackboard例子应用程序来托管一个双参数,监视该双参数的更新。按下面内容对构造函数进行修改:
// Now, add a callback to monitor any changes to the remote node's parameter. In this
// case, we supply the remote node name.
auto cb2 = [this](const rclcpp::Parameter & p) {
RCLCPP_INFO(
this->get_logger(), "cb2: Received an update to parameter \"%s\" of type: %s: \"%.02lf\"",
p.get_name().c_str(),
p.get_type_name().c_str(),
p.as_double());
};
auto remote_node_name = std::string("parameter_blackboard");
auto remote_param_name = std::string("a_double_param");
cb_handle2_ = param_subscriber_->add_parameter_callback(remote_param_name, cb2, remote_node_name);
private:
std::shared_ptr<rclcpp::ParameterEventHandler> param_subscriber_;
std::shared_ptr<rclcpp::ParameterCallbackHandle> cb_handle_;
std::shared_ptr<rclcpp::ParameterCallbackHandle> cb_handle2_; // Add this
};
再次回到工作空间根路径重新构建包:
$colcon build --packages-select cpp_parameter_event_handler
source一下环境:
$source install/setup.bash
运行parameter_event_handler:
$ros2 run cpp_parameter_event_handler parameter_event_handler
打开另外一个终端(记得source环境),运行parameter_blackboard例子:
$ros2 run demo_nodes_cpp parameter_blackboard
我们再打开另外一个终端,设置下parameter_blackboard例子中的参数:
$ros2 param set parameter_blackboard a_double_param 3.45
我们再看看返回:
(关于C++的一些新特性,ROS(2)中用的挺多的,如果对此不熟悉,比如我本人,挺影响ROS的后续学习,不过可以找些书籍充个电,工欲善其事必先利其器嘛,我这有两本电子书《深入应用C++11:代码优化与工程级应用》、《Effective Modern C++(中文版)》,如有需要可以私信或评论区留下邮箱,免费发放)
本篇完。