Parameter

导言

在我们的机器人控制中,如果在机器人启动之后还需要修改类似于速度、路径之类的数据,我们不可能每次都重新向节点发送一个完整的新的请求,这样的工作量太大了

因此,我们可以使用参数通信方式,实现更轻松地调整一些节点的参数

这里值得注意的是,笔者不认为参数同另外三种通信方式同级,而是作为一种附加型的通信方式,用于辅助其他通信的存在

下面我们直接通过例子强化理解

C++

创建功能包并编写节点

创建功能包

我们这次的目标是创建一个功能包和测试用的节点,使用参数的方法将进行动态调参,使他打印不同级别的日志

cd ros2_learning
mkdir -p Param/param_cpp_ws
ros2 pkg create example_parameters_rclcpp --build-type ament_cmake --dependencies rclcpp

编写节点

#include <chrono>
#include "rclcpp/rclcpp.hpp"

class ParametersBasicNode : public rclcpp::Node {
 public:
  explicit ParametersBasicNode(std::string name) : Node(name) {
    RCLCPP_INFO(this->get_logger(), "节点已启动:%s.", name.c_str());
    this->declare_parameter("rcl_log_level", 0);
    this->get_parameter("rcl_log_level", log_level);
    this->get_logger().set_level((rclcpp::Logger::Level)log_level);
    using namespace std::literals::chrono_literals;
    timer_ = this->create_wall_timer(
        500ms, std::bind(&ParametersBasicNode::timer_callback, this));
  }

 private:
  int log_level;
  rclcpp::TimerBase::SharedPtr timer_;

  void timer_callback() {
    this->get_parameter("rcl_log_level", log_level);
    this->get_logger().set_level((rclcpp::Logger::Level)log_level);
    std::cout<<"======================================================"<<std::endl;
    RCLCPP_DEBUG(this->get_logger(), "我是DEBUG级别的日志,我被打印出来了!");
    RCLCPP_INFO(this->get_logger(), "我是INFO级别的日志,我被打印出来了!");
    RCLCPP_WARN(this->get_logger(), "我是WARN级别的日志,我被打印出来了!");
    RCLCPP_ERROR(this->get_logger(), "我是ERROR级别的日志,我被打印出来了!");
    RCLCPP_FATAL(this->get_logger(), "我是FATAL级别的日志,我被打印出来了!");
  }
};

int main(int argc, char** argv) {
  rclcpp::init(argc, argv);
  auto node = std::make_shared<ParametersBasicNode>("parameters_basic");
  rclcpp::spin(node);
  rclcpp::shutdown();
  return 0;
}

我们简单解释一下上面的代码:

  • 首先日志是有等级的,可以通过set_level()方法设置允许显示的等级

  • declare_parameter,表示声明我们的参数,并且初始值定为0

  • get_parameter,表示获取我们的参数值,并放到后面的变量中

  • 我们这里使用了定时器来设置参数的刷新时间,毕竟参数没有设置很复杂的通信模式,那我们自然需要牺牲一部分实时性来使用刷新的模式更新我们的参数

然后我们就可以编译测试了

啊对,参数就这么简单,所以我认为这是一篇大水 blog(雾

Python

同样的方法创建功能包,然后写出下面这个节点:

import rclpy
from rclpy.node import Node

class ParametersBasicNode(Node):
    """
    创建一个ParametersBasicNode节点,并在初始化时输出一个话
    """

    def __init__(self, name):
        super().__init__(name)
        self.get_logger().info(f"节点已启动:{name}!")
        self.declare_parameter('rcl_log_level', 0)
        log_level = self.get_parameter("rcl_log_level").value
        self.get_logger().set_level(log_level)
        self.timer = self.create_timer(0.5, self.timer_callback)

    def timer_callback(self):
        log_level = self.get_parameter("rcl_log_level").value
        self.get_logger().set_level(log_level)
        print(
            f"========================{log_level}=============================")
        self.get_logger().debug("我是DEBUG级别的日志,我被打印出来了!")
        self.get_logger().info("我是INFO级别的日志,我被打印出来了!")
        self.get_logger().warn("我是WARN级别的日志,我被打印出来了!")
        self.get_logger().error("我是ERROR级别的日志,我被打印出来了!")
        self.get_logger().fatal("我是FATAL级别的日志,我被打印出来了!")



def main(args=None):
    rclpy.init(args=args)
    node = ParametersBasicNode("parameters_basic")
    rclpy.spin(node)
    rclpy.shutdown()

然后这里的代码也相当简单了,和 C++ 的逻辑是一样的,所以就不需要多做说明了(

posted @ 2025-12-01 11:40  Liehu404  阅读(14)  评论(0)    收藏  举报