在 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参数文件
        )
    ])

总结

  • 命令行导出:简单快捷,适合手动保存运行中节点的参数。
  • 代码中保存:灵活可控,适合自动保存或复杂场景(如条件触发)。
    根据需求选择合适的方法即可。
Logo

北京人形旗下天工造物具身智能开源社区,聚焦具身天工与慧思开物两大平台

更多推荐