ros2 节点参数保存为yaml 文件

在 ROS 2 中,将节点参数保存为 YAML 文件可以通过两种方式实现:命令行工具导出在代码中手动保存。以下是详细步骤和示例:

一、方法 1:使用 ROS 2 命令行工具导出参数(推荐)

ROS 2 提供了 ros2 param dump 命令,可以直接将运行中节点的所有参数导出为 YAML 文件,无需修改代码。

步骤:
  1. 确保节点正在运行
    先启动你的 ROS 2 节点,例如:

    bash

  • ros2 run your_package your_node
    
  • 查看节点名称
    ros2 node list 确认节点的完整名称(例如 /my_controller_node):

    bash

  • ros2 node list
    
  • 导出参数到 YAML 文件
    使用 ros2 param dump 命令,格式为:

    bash

ros2 param dump <节点名称> -o <输出文件路径>

示例:

bash

  1. ros2 param dump /my_controller_node -o params.yaml
    
     

    执行后,当前目录会生成 params.yaml 文件,包含节点的所有参数。

二、方法 2:在 C++ 代码中手动保存参数到 YAML

如果需要在节点运行过程中自动保存参数(例如在退出时或触发某个事件时),可以通过代码读取参数后写入 YAML 文件。需要依赖 yaml-cpp 库处理 YAML 格式。

步骤:
  1. 添加依赖
    package.xml 中添加 yaml-cpp 依赖:

    xml

<depend>yaml-cpp</depend>

CMakeLists.txt 中添加:

cmake

  • find_package(yaml-cpp REQUIRED)
    target_link_libraries(your_node_name PRIVATE yaml-cpp)
    
  • 代码实现
    在节点中添加参数保存逻辑,示例代码:

    cpp

运行

  1. #include "rclcpp/rclcpp.hpp"
    #include "yaml-cpp/yaml.h"
    #include <fstream>
    #include <vector>
    
    class MyNode : public rclcpp::Node {
    public:
        MyNode() : Node("my_node") {
            // 声明参数(示例)
            this->declare_parameter("max_speed", 0.5);
            this->declare_parameter("robot_name", "my_robot");
            this->declare_parameter("enable_sensor", true);
            this->declare_parameter("joint_limits", std::vector<double>{1.0, 2.0, 3.0});
    
            // 触发保存参数(例如在节点关闭时)
            save_params_timer_ = this->create_wall_timer(
                std::chrono::seconds(10),  // 每10秒保存一次,或按需修改触发条件
                std::bind(&MyNode::save_params_to_yaml, this)
            );
        }
    
    private:
        void save_params_to_yaml() {
            // 1. 读取所有参数名称
            std::vector<std::string> param_names = this->list_parameters({}, 1000).names;
    
            // 2. 创建YAML文档
            YAML::Node yaml_node;
    
            // 3. 遍历参数并写入YAML
            for (const auto& param_name : param_names) {
                // 处理参数类型(支持常见类型:double、int、bool、string、vector等)
                if (this->has_parameter(param_name)) {
                    auto param_value = this->get_parameter(param_name).get_value<rclcpp::ParameterValue>();
                    
                    if (param_value.get_type() == rclcpp::ParameterType::PARAMETER_DOUBLE) {
                        yaml_node[param_name] = param_value.get<double>();
                    } else if (param_value.get_type() == rclcpp::ParameterType::PARAMETER_INTEGER) {
                        yaml_node[param_name] = param_value.get<int>();
                    } else if (param_value.get_type() == rclcpp::ParameterType::PARAMETER_BOOL) {
                        yaml_node[param_name] = param_value.get<bool>();
                    } else if (param_value.get_type() == rclcpp::ParameterType::PARAMETER_STRING) {
                        yaml_node[param_name] = param_value.get<std::string>();
                    } else if (param_value.get_type() == rclcpp::ParameterType::PARAMETER_DOUBLE_ARRAY) {
                        yaml_node[param_name] = param_value.get<std::vector<double>>();
                    } else if (param_value.get_type() == rclcpp::ParameterType::PARAMETER_INTEGER_ARRAY) {
                        yaml_node[param_name] = param_value.get<std::vector<int>>();
                    }
                }
            }
    
            // 4. 写入YAML文件
            std::ofstream fout("saved_params.yaml");
            if (fout.is_open()) {
                fout << yaml_node << std::endl;
                RCLCPP_INFO(this->get_logger(), "参数已保存到 saved_params.yaml");
            } else {
                RCLCPP_ERROR(this->get_logger(), "无法打开文件 saved_params.yaml");
            }
        }
    
        rclcpp::TimerBase::SharedPtr save_params_timer_;
    };
    
    int main(int argc, char* argv[]) {
        rclcpp::init(argc, argv);
        rclcpp::spin(std::make_shared<MyNode>());
        rclcpp::shutdown();
        return 0;
    }
    
  2. 编译运行
    编译后运行节点,会自动生成 saved_params.yaml 文件,包含所有参数。

三、YAML 文件格式说明

导出的 YAML 文件格式示例(包含不同类型的参数):

yaml

/my_node:  # 节点名称(命名空间)
  max_speed: 0.5
  robot_name: "my_robot"
  enable_sensor: true
  joint_limits: [1.0, 2.0, 3.0]

  • 节点名称作为顶级键,避免不同节点的参数冲突。
  • 支持常见数据类型:数值、布尔值、字符串、数组等。

四、扩展:使用保存的 YAML 文件加载参数

保存的 YAML 文件可用于启动节点时加载参数:

bash

ros2 run your_package your_node --ros-args --params-file params.yaml

或在 launch 文件中引用:

python

运行

from launch import LaunchDescription
from launch_ros.actions import Node

def generate_launch_description():
    return LaunchDescription([
        Node(
            package="your_package",
            executable="your_node",
            parameters=["params.yaml"]  # 加载YAML参数文件
        )
    ])

总结

  • 命令行导出:简单快捷,适合手动保存运行中节点的参数。
  • 代码中保存:灵活可控,适合自动保存或复杂场景(如条件触发)。
    根据需求选择合适的方法即可。
ROS 2中,使用YAML文件节点配置参数是一种常见且高效的方式,尤其适用于参数较多或需要动态调整的场景。以下是详细的操作步骤: ### 3.1 创建YAML参数文件 首先,需要创建一个YAML文件来存储参数。假设你的节点名为 `my_node`,可以创建一个名为 `my_params.yaml` 的文件,其内容如下: ```yaml my_node: ros__parameters: int_param: 42 str_param: "hello_ros2" double_param: 3.14 bool_param: true list_param: [1, 2, 3] ``` 在这个YAML文件中,`my_node` 是节点的名称,`ros__parameters` 是ROS 2中用于声明参数的特殊关键字,下面的键值对即为节点参数配置[^2]。 ### 3.2 启动节点并加载YAML参数 在启动节点时,可以通过命令行参数指定YAML文件路径来加载参数。假设YAML文件位于 `$(pwd)/src/yaml_params_demo/config/params.yaml`,可以使用以下命令启动节点: ```bash ros2 run yaml_params_demo yaml_params_node --ros-args -p yaml_file_path:=$(pwd)/src/yaml_params_demo/config/params.yaml ``` 该命令中,`--ros-args` 表示后续参数ROS 2节点参数,`-p yaml_file_path:=...` 指定了YAML文件的路径[^1]。 ### 3.3 在C++代码中声明并使用参数 在C++节点代码中,需要声明这些参数并读取其值。以下是一个简单的示例代码片段: ```cpp #include "rclcpp/rclcpp.hpp" class MyNode : public rclcpp::Node { public: MyNode() : Node("my_node") { // 声明参数 this->declare_parameter<int>("int_param", 0); this->declare_parameter<std::string>("str_param", ""); this->declare_parameter<double>("double_param", 0.0); this->declare_parameter<bool>("bool_param", false); this->declare_parameter<std::vector<int>>("list_param", {}); // 获取参数值 int int_value = this->get_parameter("int_param").as_int(); std::string str_value = this->get_parameter("str_param").as_string(); double double_value = this->get_parameter("double_param").as_double(); bool bool_value = this->get_parameter("bool_param").as_bool(); std::vector<int> list_value = this->get_parameter("list_param").as_integer_array(); // 打印参数值 RCLCPP_INFO(this->get_logger(), "int_param: %d", int_value); RCLCPP_INFO(this->get_logger(), "str_param: %s", str_value.c_str()); RCLCPP_INFO(this->get_logger(), "double_param: %.2f", double_value); RCLCPP_INFO(this->get_logger(), "bool_param: %s", bool_value ? "true" : "false"); RCLCPP_INFO(this->get_logger(), "list_param: [%d, %d, %d]", list_value[0], list_value[1], list_value[2]); } }; int main(int argc, char *argv[]) { rclcpp::init(argc, argv); auto node = std::make_shared<MyNode>(); rclcpp::spin(node); rclcpp::shutdown(); return 0; } ``` 在上述代码中,`declare_parameter` 用于声明参数,`get_parameter` 用于获取参数值,`RCLCPP_INFO` 用于打印日志信息[^3]。 ### 3.4 使用Launch文件加载YAML参数 除了通过命令行加载YAML文件,还可以通过Launch文件实现。以下是一个简单的Launch文件示例: ```python from launch import LaunchDescription from launch_ros.actions import Node import os from ament_index_python.packages import get_package_share_directory def generate_launch_description(): config = os.path.join( get_package_share_directory('bag_to_image'), 'config', 'params.yaml' ) return LaunchDescription([ Node( package='bag_to_image', executable='bag_to_image_node', name='bag_to_image_node', parameters=[config] ) ]) ``` 通过 `parameters=[config]` 参数,可以将YAML文件中的参数加载到节点中[^4]。 ### 3.5 验证参数是否正确加载 启动节点后,可以通过查看日志输出或使用 `ros2 param get` 命令来验证参数是否正确加载。例如: ```bash ros2 param get /my_node int_param ``` 该命令将返回 `int_param` 参数的值,确认其是否与YAML文件中的配置一致[^5]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值