ROS2 节点中使用参数

修改service_practice_ws/src/demo_cpp_service/src/patrol_client.cpp

cpp 复制代码
#include <cstdlib>
#include <ctime>
#include <chrono>
#include "rclcpp/rclcpp.hpp"
#include "service_interface/srv/patrol.hpp"
#include "rcl_interfaces/msg/parameter.hpp"
#include "rcl_interfaces/msg/parameter_value.hpp"
#include "rcl_interfaces/msg/parameter_type.hpp"
#include "rcl_interfaces/srv/set_parameters.hpp"

using SetP = rcl_interfaces::srv::SetParameters;
using namespace std::chrono_literals;
using Patrol = service_interface::srv::Patrol;

class PatrolClient : public rclcpp::Node
{
private:
    rclcpp::TimerBase::SharedPtr timer_;
    rclcpp::Client<Patrol>::SharedPtr patrol_client_;

public:
    PatrolClient() : Node("patrol_client")
    {
        patrol_client_ = this->create_client<Patrol>("patrol");
        timer_ = this->create_wall_timer(6s, std::bind(&PatrolClient::timer_callback, this));
    }

    void timer_callback()
    {
        while(!patrol_client_->wait_for_service(std::chrono::seconds(1)))
        {
            if (!rclcpp::ok())
            {
                RCLCPP_ERROR(this->get_logger(), "interrupted when wait for service");
                return;
            }
            RCLCPP_INFO(this->get_logger(), "wait for server..");
        }
        auto request = std::make_shared<Patrol::Request>();
        request->target_x = rand() % 15;
        request->target_y = rand() % 15;
        RCLCPP_INFO(this->get_logger(), "request for patrol (%f, %f)", request->target_x, request->target_y);
        patrol_client_->async_send_request(
            request,
            [&](rclcpp::Client<Patrol>::SharedFuture result_future) -> void
            {
                auto response = result_future.get();
                if(response->result == Patrol::Response::SUCCESS)
                {
                    RCLCPP_INFO(this->get_logger(), "process success");
                }
                else if(response->result == Patrol::Response::FAIL)
                {
                    RCLCPP_INFO(this->get_logger(), "process failed");
                }
            }
        );
    }

    std::shared_ptr<SetP::Response> call_set_parameters(rcl_interfaces::msg::Parameter& parameter)
    {
        auto param_client = this->create_client<SetP>("/turtle_controller/set_parameters");
        while(!param_client->wait_for_service(std::chrono::seconds(1)))
        {
            if(!rclcpp::ok())
            {
                RCLCPP_ERROR(this->get_logger(), "interrupted when wait service");
                return nullptr;
            }
            RCLCPP_INFO(this->get_logger(), "wait service");
        }
        auto request = std::make_shared<SetP::Request>();
        request->parameters.push_back(parameter);

        auto future = param_client->async_send_request(request);
        rclcpp::spin_until_future_complete(this->get_node_base_interface(), future);
        auto response = future.get();
        return response;
    }

    void update_server_param_k(double k)
    {
        auto param = rcl_interfaces::msg::Parameter();
        param.name = "k";
        auto param_value = rcl_interfaces::msg::ParameterValue();
        param_value.type = rcl_interfaces::msg::ParameterType::PARAMETER_DOUBLE;
        param_value.double_value = k;
        param.value = param_value;
        auto response = call_set_parameters(param);
        if(response == nullptr)
        {
            RCLCPP_WARN(this->get_logger(), "update parameter failed");
            return;
        }
        else
        {
            for(auto result : response->results)
            {
                if (result.successful)
                {
                    RCLCPP_INFO(this->get_logger(), "parameter k is updated: %f", k);
                }
                else
                {
                    RCLCPP_WARN(this->get_logger(), "parameter k update failed for : %s", result.reason.c_str());
                }
            }
        }
    }
};

int main(int argc, char *argv[])
{
    rclcpp::init(argc, argv);
    auto node = std::make_shared<PatrolClient>();
    node->update_server_param_k(1.5);
    rclcpp::spin(node);
    rclcpp::shutdown();
    return 0;
}

修改service_practice_ws/src/demo_cpp_service/src/turtle_control.cpp

cpp 复制代码
#include "rclcpp/rclcpp.hpp"
#include "service_interface/srv/patrol.hpp"
#include "turtlesim/msg/pose.hpp"
#include "geometry_msgs/msg/twist.hpp"
#include "rcl_interfaces/msg/set_parameters_result.hpp"
using service_interface::srv::Patrol;
using SetParametersResult = rcl_interfaces::msg::SetParametersResult;

class TurtleController : public rclcpp::Node
{
public:
    TurtleController() : Node("turtle_controller")
    {
        this->declare_parameter("k", 1.0);
        this->declare_parameter("max_speed", 1.0);
        this->get_parameter("k", k_);
        this->get_parameter("max_speed", max_speed_);
        velocity_publisher_ = this->create_publisher<geometry_msgs::msg::Twist>("/turtle1/cmd_vel", 10);
        pose_subscription_ = this->create_subscription<turtlesim::msg::Pose>("/turtle1/pose", 10,
            std::bind(&TurtleController::on_pose_received_, this, std::placeholders::_1));
        //添加服务
        patrol_server_ = this->create_service<Patrol>(
            "patrol",
        [&](const std::shared_ptr<Patrol::Request> request,
        std::shared_ptr<Patrol::Response> response) -> void{
            if((0 < request->target_y && request->target_x < 12.0f)
            && (0 < request->target_y && request->target_y < 12.0f)){
                target_x_ = request->target_x;
                target_y_ = request->target_y;
                response->result = Patrol::Response::SUCCESS;
            }
            else
            {
                response->result = Patrol::Response::FAIL;
            }
        }
        );
        //添加参数设置回调
        parameters_callback_handle_ = this->add_on_set_parameters_callback(
            [&](const std::vector<rclcpp::Parameter>& parameters)->SetParametersResult
            {
                for(auto parameter : parameters)
                {
                    RCLCPP_INFO(this->get_logger(), "set parameter %s to %f", parameter.get_name().c_str(), parameter.as_double());
                    if (parameter.get_name() == "k")
                    {
                        k_ = parameter.as_double();
                    }
                    else if(parameter.get_name() == "max_speed")
                    {
                        max_speed_ = parameter.as_double();
                    }
                }
                auto result = SetParametersResult();
                result.successful = true;
                return result;
            }
        );
        velocity_publisher_ = this->create_publisher<geometry_msgs::msg::Twist>("/turtle1/cmd_vel", 10);
    }

    void on_pose_received_(const turtlesim::msg::Pose::SharedPtr pose)
    {
        auto message = geometry_msgs::msg::Twist();
        double current_x = pose->x;
        double current_y = pose->y;
        // RCLCPP_INFO(this->get_logger(), "current location: (x=%f, y=%f)", current_x, current_y);

        double distance = std::sqrt((target_x_ - current_x)*(target_x_-current_x)+(target_y_-current_y)*(target_y_-current_y));
        double angle = std::atan2(target_y_-current_y, target_x_-current_x)-pose->theta;

        if(distance>0.1)
        {
            if (fabs(angle)>0.2)    
            {
                message.angular.z = fabs(angle);
            }
            else
            {
                message.linear.x = k_*distance;
            }
            
        }


        if (message.linear.x > max_speed_)
        {
            message.linear.x = max_speed_;
        }
        velocity_publisher_->publish(message);
        
    }

private:
    rclcpp::Service<Patrol>::SharedPtr patrol_server_;
    rclcpp::Subscription<turtlesim::msg::Pose>::SharedPtr pose_subscription_;
    rclcpp::Publisher<geometry_msgs::msg::Twist>::SharedPtr velocity_publisher_;
    OnSetParametersCallbackHandle::SharedPtr parameters_callback_handle_;
    double target_x_{0.0};
    double target_y_{0.0};
    double k_{1.0};
    double max_speed_{7.0};
    
};

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

构建运行查看结果,可以发现在/turtle_controller下面有kmax_speed服务

bash 复制代码
colcon build
ros2 run turtlesim turtlesim_node
ros2 run demo_cpp_service patrol_client
ros2 run demo_cpp_service turtle_control

ros2 param list
----------------------------输出-----------------------------
/patrol_client:
  qos_overrides./parameter_events.publisher.depth
  qos_overrides./parameter_events.publisher.durability
  qos_overrides./parameter_events.publisher.history
  qos_overrides./parameter_events.publisher.reliability
  use_sim_time
/rqt_gui_py_node_1968386:
  use_sim_time
/turtle_controller:
  k
  max_speed
  qos_overrides./parameter_events.publisher.depth
  qos_overrides./parameter_events.publisher.durability
  qos_overrides./parameter_events.publisher.history
  qos_overrides./parameter_events.publisher.reliability
  use_sim_time
/turtlesim:
  background_b
  background_g
  background_r
  qos_overrides./parameter_events.publisher.depth
  qos_overrides./parameter_events.publisher.durability
  qos_overrides./parameter_events.publisher.history
  qos_overrides./parameter_events.publisher.reliability
  use_sim_time
相关推荐
froginwe11几秒前
JavaScript 函数调用
开发语言
独望漫天星辰5 分钟前
C++ 多态深度解析:从语法规则到底层实现(附实战验证代码)
开发语言·c++
无小道23 分钟前
Qt——事件简单介绍
开发语言·前端·qt
devmoon28 分钟前
在 Paseo 测试网上获取 Coretime:On-demand 与 Bulk 的完整实操指南
开发语言·web3·区块链·测试用例·智能合约·solidity
kylezhao20191 小时前
C# 中的 SOLID 五大设计原则
开发语言·c#
王老师青少年编程1 小时前
2024年信奥赛C++提高组csp-s初赛真题及答案解析(阅读程序第3题)
c++·题解·真题·csp·信奥赛·csp-s·提高组
凡人叶枫1 小时前
C++中输入、输出和文件操作详解(Linux实战版)| 从基础到项目落地,避坑指南
linux·服务器·c语言·开发语言·c++
CSDN_RTKLIB1 小时前
使用三方库头文件未使用导出符号情景
c++
春日见2 小时前
车辆动力学:前后轮车轴
java·开发语言·驱动开发·docker·计算机外设
锐意无限2 小时前
Swift 扩展归纳--- UIView
开发语言·ios·swift