参数服务器 server and client

ROS2 参数服务器和客户端实现利用了 ROS2 内置的参数服务机制,具有以下特点:

  1. 服务器节点(param_server_node)

    • 初始化并维护参数存储
    • 定期打印当前所有参数状态
    • 支持客户端的参数查询、设置和删除操作
  2. 客户端节点(param_client_node)

    • 使用SyncParametersClient与参数服务器交互
    • 提供参数的获取、设置、更新和删除示例
    • 等待服务器可用后再执行操作
  3. 项目结构

    • 包含完整的 CMakeLists.txt 和 package.xml 配置文件
    • 符合 ROS2 的包结构规范

使用方法

  1. 创建 ROS2 工作空间并构建包:

    bash

    mkdir -p ~/ros2_ws/src
    cd ~/ros2_ws/src

    创建包

    ros2 pkg create --build-type ament_cmake parameter_server_example

    将上述代码文件放入相应位置

    cd ~/ros2_ws
    colcon build
    source install/setup.bash

  • 运行参数服务器:

    bash

    ros2 run parameter_server_example param_server

  • 在另一个终端运行参数客户端:

    bash

    source ~/ros2_ws/install/setup.bash
    ros2 run parameter_server_example param_client

客户端会执行一系列参数操作并输出结果,服务器则会每 10 秒打印一次当前所有参数的状态。

这种实现充分利用了 ROS2 的参数系统,比直接使用套接字实现的参数服务器更符合 ROS2 的生态系统和设计理念。

param_server_node.cpp

#include "rclcpp/rclcpp.hpp"

#include <unordered_map>

#include <string>

class ParamServerNode : public rclcpp::Node

{

public:

ParamServerNode() : Node("param_server_node")

{

// 初始化一些默认参数

declare_parameter("max_connections", 10);

declare_parameter("timeout", 5.0);

declare_parameter("enabled", true);

declare_parameter("server_name", "main_server");

RCLCPP_INFO(get_logger(), "参数服务器节点已启动");

// 创建一个定时器用于周期性打印当前参数状态

timer_ = this->create_wall_timer(

std::chrono::seconds(10),

std::bind(&ParamServerNode::print_parameters, this)

);

}

private:

void print_parameters()

{

RCLCPP_INFO(get_logger(), "\n当前参数列表:");

// 获取所有参数名称

auto param_names = get_parameter_names();

for (const auto& name : param_names) {

rclcpp::Parameter param;

if (get_parameter(name, param)) {

RCLCPP_INFO(get_logger(), "%s: %s",

name.c_str(),

param.value_to_string().c_str());

}

}

}

rclcpp::TimerBase::SharedPtr timer_;

};

int main(int argc, char * argv\[\])

{

rclcpp::init(argc, argv);

rclcpp::spin(std::make_shared<ParamServerNode>());

rclcpp::shutdown();

return 0;

}

param_client_node.cpp

#include "rclcpp/rclcpp.hpp"

#include <chrono>

#include <thread>

class ParamClientNode : public rclcpp::Node

{

public:

ParamClientNode() : Node("param_client_node")

{

RCLCPP_INFO(get_logger(), "参数客户端节点已启动");

// 创建参数客户端

param_client_ = std::make_shared<rclcpp::SyncParametersClient>(this, "param_server_node");

// 等待参数服务器可用

while (!param_client_->wait_for_service(std::chrono::seconds(1))) {

if (!rclcpp::ok()) {

RCLCPP_ERROR(get_logger(), "等待参数服务器时被中断");

return;

}

RCLCPP_INFO(get_logger(), "等待参数服务器...");

}

// 执行参数操作示例

perform_parameter_operations();

}

private:

void perform_parameter_operations()

{

// 获取参数

get_parameters_example();

// 设置新参数

set_parameters_example();

// 更新已有参数

update_parameters_example();

// 删除参数

delete_parameters_example();

// 再次获取参数以显示变化

get_parameters_example();

}

void get_parameters_example()

{

RCLCPP_INFO(get_logger(), "\n--- 获取参数示例 ---");

// 获取单个参数

auto max_connections = param_client_->get_parameter<int>("max_connections");

RCLCPP_INFO(get_logger(), "max_connections: %d", max_connections);

// 批量获取参数

std::vector<std::string> param_names = {"timeout", "enabled", "server_name"};

auto params = param_client_->get_parameters(param_names);

for (const auto& param : params) {

RCLCPP_INFO(get_logger(), "%s: %s",

param.get_name().c_str(),

param.value_to_string().c_str());

}

}

void set_parameters_example()

{

RCLCPP_INFO(get_logger(), "\n--- 设置新参数示例 ---");

std::vector<rclcpp::Parameter> params;

params.push_back(rclcpp::Parameter("buffer_size", 1024));

params.push_back(rclcpp::Parameter("log_level", "info"));

params.push_back(rclcpp::Parameter("timeout_ms", 5000));

auto results = param_client_->set_parameters(params);

for (size_t i = 0; i < results.size(); ++i) {

if (resultsi.successful) {

RCLCPP_INFO(get_logger(), "成功设置参数: %s", paramsi.get_name().c_str());

} else {

RCLCPP_ERROR(get_logger(), "设置参数失败: %s", paramsi.get_name().c_str());

}

}

}

void update_parameters_example()

{

RCLCPP_INFO(get_logger(), "\n--- 更新参数示例 ---");

std::vector<rclcpp::Parameter> params;

params.push_back(rclcpp::Parameter("max_connections", 20));

params.push_back(rclcpp::Parameter("timeout", 10.0));

params.push_back(rclcpp::Parameter("enabled", false));

auto results = param_client_->set_parameters(params);

for (size_t i = 0; i < results.size(); ++i) {

if (resultsi.successful) {

RCLCPP_INFO(get_logger(), "成功更新参数: %s", paramsi.get_name().c_str());

} else {

RCLCPP_ERROR(get_logger(), "更新参数失败: %s", paramsi.get_name().c_str());

}

}

}

void delete_parameters_example()

{

RCLCPP_INFO(get_logger(), "\n--- 删除参数示例 ---");

std::vector<std::string> params_to_delete = {"server_name", "timeout_ms"};

auto results = param_client_->delete_parameters(params_to_delete);

for (size_t i = 0; i < results.size(); ++i) {

if (resultsi.successful) {

RCLCPP_INFO(get_logger(), "成功删除参数: %s", params_to_deletei.c_str());

} else {

RCLCPP_ERROR(get_logger(), "删除参数失败: %s", params_to_deletei.c_str());

}

}

}

rclcpp::SyncParametersClient::SharedPtr param_client_;

};

int main(int argc, char * argv\[\])

{

rclcpp::init(argc, argv);

rclcpp::spin(std::make_shared<ParamClientNode>());

rclcpp::shutdown();

return 0;

}

CmakeList.txt

cmake_minimum_required(VERSION 3.5)

project(parameter_server_example)

if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")

add_compile_options(-Wall -Wextra -Wpedantic)

endif()

查找依赖

find_package(ament_cmake REQUIRED)

find_package(rclcpp REQUIRED)

声明服务器节点

add_executable(param_server src/param_server_node.cpp)

ament_target_dependencies(param_server rclcpp)

声明客户端节点

add_executable(param_client src/param_client_node.cpp)

ament_target_dependencies(param_client rclcpp)

安装目标

install(TARGETS

param_server

param_client

DESTINATION lib/${PROJECT_NAME})

ament_package()

packages.xml

<?xml version="1.0"?>

<?xml-model href="http://download.ros.org/schema/package_format3.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?>

<package format="3">

<name>parameter_server_example</name>

<version>0.0.0</version>

<description>ROS2参数服务器和客户端示例</description>

<maintainer email="your@email.com">Your Name</maintainer>

<license>Apache-2.0</license>

<buildtool_depend>ament_cmake</buildtool_depend>

<depend>rclcpp</depend>

<build_depend>ament_cmake</build_depend>

<exec_depend>rclcpp</exec_depend>

<build_depend>ament_cmake</build_depend>

<exec_depend>rclcpp</exec_depend>

<export>

<build_type>ament_cmake</build_type>

</export>

</package>

相关推荐
波波0072 小时前
C# 15 重磅新特性: 带标签 break 与 continue:重新定义嵌套循环控制流
服务器·前端·c#
隔窗听雨眠4 小时前
GBase 8s并发控制深度解析:封锁机制、隔离级别与死锁处理全攻略
服务器·数据库·oracle
鲸采云SRM采购管理系统5 小时前
采购管理系统哪家好?2026最新测评对比
java·服务器·数据库
C++ 老炮儿的技术栈5 小时前
基于Qt实现轻量化本地音乐播放器
开发语言·c++·qt·c·播放器·音乐
那年窗外下的雪.6 小时前
AIDC 学习日志 第 04 天 BGP Underlay 基础与路由选择
服务器·学习·php
0x536 小时前
Java网络编程(二)
java·服务器·网络
果果燕7 小时前
C++学习笔记(三):类与对象拓展学习笔记
java·服务器·前端
小绫网络安全8 小时前
Kali Linux渗透测试入门教程:从零搭建到实战攻防
linux·运维·服务器
allforgood8 小时前
控制启动过程
linux·运维·服务器
西安景驰电子8 小时前
《PTP精确时间协议系列》第一篇:从原理到应用,全面解读IEEE 1588
linux·运维·服务器·开发语言·网络·windows·php