系列文章目录
留空
文章目录
- 系列文章目录
- 前言
- 一、题目
- 二、使用RCLCPP编写参数
- 三、完整代码
- 四、测试
- 1.用命令行查看参数
- 2.修改参数
- 总结
前言
自用
一、题目
通过参数实现动态调整 张三买书时 给王五 钱 的金额。
常用的编写参数的函数:declare_parameter
声明和初始化一个参数declare_parameters
声明和初始化一堆参数get_parameter
通过参数名字获取一个参数get_parameters
获取具有给定前缀的所有参数的参数值set_parameters
设置一组参数的值
完成张三买书时 给王五 钱 的参数的更改,我们只需要做两步即可,声明参数和获取参数
根据上一篇,稍微粗略的修改了一下代码
wang5.cpp
修改了SellNovel_callback
#include "rclcpp/rclcpp.hpp"
//(1)导入订阅的话题接口类型
#include "std_msgs/msg/string.hpp"
//1.导入服务接口
#include "learning_interfaces1/srv/sell_novel.hpp"
// 引入C++标准库中的队列容器模板(先进先出(FIFO)的数据结构)
#include <queue>
class ReadersAndSellServer : public rclcpp::Node
{
public:
ReadersAndSellServer(std::string name) : Node(name)
{
RCLCPP_INFO(this->get_logger(),"读者节点%s已启动",name.c_str());
RCLCPP_INFO(this->get_logger(),"卖书服务端%s已启动",name.c_str());
//(3)创建订阅者
sub_readers = this->create_subscription<std_msgs::msg::String>
("no_time",10,std::bind(&ReadersAndSellServer::readnovels_callback,this,std::placeholders::_1));
// 5、创建一个服务回调组
callback_group_service = this->create_callback_group(rclcpp::CallbackGroupType::MutuallyExclusive);
// 4、创建服务端
sellserver = this->create_service<learning_interfaces1::srv::SellNovel>
("sell_novels",std::bind(&ReadersAndSellServer::SellNovel_callback,this,std::placeholders::_1,std::placeholders::_2),
rmw_qos_profile_default,callback_group_service);
}
private:
//(2)声明订阅者
rclcpp::Subscription<std_msgs::msg::String>::SharedPtr sub_readers;
// 3、声明服务端
rclcpp::Service<learning_interfaces1::srv::SellNovel>::SharedPtr sellserver;
// 4、声明一个服务回调组
rclcpp::CallbackGroup::SharedPtr callback_group_service;
// 创建一个小说章节队列(书库)
std::queue<std::string> novels_queue;
//(4)创建订阅回调函数
void readnovels_callback(const std_msgs::msg::String::SharedPtr novels)
{
//(5)编写订阅回调函数
RCLCPP_INFO(this->get_logger(),"王五已阅读%s",novels->data.c_str());
//把收到的小说存入书库
novels_queue.push(novels->data);
}
// 2、创建服务端回调函数
void SellNovel_callback(const learning_interfaces1::srv::SellNovel::Request::SharedPtr request,
const learning_interfaces1::srv::SellNovel::Response::SharedPtr response)
{
//第一步:判断张三给的钱数是否足够(每章1元)
unsigned int sendnovel_flag = 0; //是否发送小说标志位
unsigned int buymoney = request -> money; //张三发来的买书钱
if(buymoney == 5)
{
sendnovel_flag = 1;
RCLCPP_INFO(this->get_logger(),"已收到张三%d元",buymoney);
}
else if(buymoney != 5)
{
sendnovel_flag = 0;
RCLCPP_INFO(this->get_logger(),"已收到张三%d元,付款有误,无法发送小说",buymoney);
}
//第二步:判断小说章节是否足够五章
if(novels_queue.size() < 5 && sendnovel_flag == 1)
{
RCLCPP_INFO(this->get_logger(),"当前no_time章节存量为%zu:存量不够5章,开始等待",novels_queue.size());
//设置rate周期为3s,代表3s检查一次
rclcpp::Rate loop_rate(1.0/3);
//当书库的章节小于5时,一直循环
while(novels_queue.size() < 5)
{
//显示当前书库的章节数量及缺少数量
RCLCPP_INFO(this->get_logger(),"等待中,目前已有%zu章,还差%zu章",novels_queue.size(),5-novels_queue.size());
//让整个循环3s运行一次
loop_rate.sleep();
}
}
//当章节数量达到5,跳出循环
if(sendnovel_flag == 1)
RCLCPP_INFO(this->get_logger(),"当前no_time小说存量为%zu,已满足需求,准备发送",novels_queue.size());
//第三步:把书发给张三
//把小说从书库中一章一章取出,并放进请求响应对象response中
if(sendnovel_flag == 1)
{
for(unsigned int i = 0 ; i < 5 ;i++)
{
response->novels.push_back(novels_queue.front());
novels_queue.pop();
}
}
}
};
int main(int argc,char** argv)
{
rclcpp::init(argc,argv);
auto node = std::make_shared<ReadersAndSellServer>("wang5");
//rclcpp::spin(node);
//将之前的节点执行器换成多线程执行器
rclcpp::executors::MultiThreadedExecutor exector;
exector.add_node(node);
exector.spin();
rclcpp::shutdown();
return 0;
}
zhang3.cpp
使用了定时器,修改了buynovel_callback
#include "rclcpp/rclcpp.hpp"
// 1、导入服务接口
#include "learning_interfaces1/srv/sell_novel.hpp"
class BuyNovelClient : public rclcpp::Node
{
public:
BuyNovelClient(std::string name) : Node(name)
{
RCLCPP_INFO(this->get_logger(),"买书客户端%s已启动",name.c_str());
// 5、创建客户端
buyclient = this->create_client<learning_interfaces1::srv::SellNovel>("sell_novels");
// 10、创建定时器
sendbuy_timer = this->create_wall_timer
(std::chrono::milliseconds(10000), std::bind(&BuyNovelClient::buy_novel, this));
}
// 2、创建请求函数
void buy_novel()
{
// 6、编写请求函数
RCLCPP_INFO(this->get_logger(),"去找王五买小说啦!!");
//等待服务端上线
while(!buyclient->wait_for_service(std::chrono::seconds(3))) //若上线则退出循环
{
RCLCPP_INFO(this->get_logger(),"等待卖书服务端上线中...");
}
//构造请求数据
auto request = std::make_shared<learning_interfaces1::srv::SellNovel_Request>(); //创建了一个“钱袋”
request->money = 5; //在“钱袋”里装入了5块钱
//发送异步请求
buyclient ->async_send_request
(request,std::bind(&BuyNovelClient::buynovel_callback,this,std::placeholders::_1));
}
private:
// 4、声明客户端
rclcpp::Client<learning_interfaces1::srv::SellNovel>::SharedPtr buyclient;
// 9、声明定时器
rclcpp::TimerBase::SharedPtr sendbuy_timer;
// 3、创建请求结果接收回调函数
void buynovel_callback(rclcpp::Client<learning_interfaces1::srv::SellNovel>::SharedFuture response)
{
// 7、编写请求结果接收回调函数
//获取回复的结果
auto buy_result = response.get();
RCLCPP_INFO(this->get_logger(),"已收到王五发来的小说共%zu章,准备开读",buy_result->novels.size());
//打印出小说内容
for(std::string novels : buy_result->novels)
{
RCLCPP_INFO(this->get_logger(),"在读:%s",novels.c_str());
}
RCLCPP_INFO(this->get_logger(), "小说读完了,好期待下面的章节呀!");
}
};
int main(int argc,char** argv)
{
rclcpp::init(argc,argv);
auto node = std::make_shared<BuyNovelClient>("zhang3");
//修改main函数调用请求函数
node->buy_novel();
rclcpp::spin(node);
rclcpp::shutdown();
return 0;
}
二、使用RCLCPP编写参数
打开zhang3.cpp
(1)声明参数
声明参数模版代码this->declare_parameter("参数名", 参数默认值);
//(1)声明参数
this->declare_parameter("buymoney", 5);
声明了一个名为buymoney
的参数,并为其提供了一个默认值5。如果在节点启动时没有为buymoney
参数提供值,它将默认为5。
(2)获取参数
获取参数的模板代码this->get_parameter("参数名");
//(2)获取参数
int money = this->get_parameter("buymoney").as_int();
获取名为buymoney
的参数,并将其转换为整数类型赋值给money
变量。虽然get_parameter
是获取参数的基本调用,但直接这样调用返回的是一个rclcpp::Parameter
对象,而不是参数的实际值。我们就要转换成整数类型,.as_int()
是一个成员函数,用于将获取到的参数值转换为整数类型。
三、完整代码
#include "rclcpp/rclcpp.hpp"
// 1、导入服务接口
#include "learning_interfaces1/srv/sell_novel.hpp"
class BuyNovelClient : public rclcpp::Node
{
public:
BuyNovelClient(std::string name) : Node(name)
{
RCLCPP_INFO(this->get_logger(),"买书客户端%s已启动",name.c_str());
// 5、创建客户端
buyclient = this->create_client<learning_interfaces1::srv::SellNovel>("sell_novels");
//(1)声明参数
this->declare_parameter("buymoney", 5);
// 10、创建定时器
sendbuy_timer = this->create_wall_timer
(std::chrono::milliseconds(10000), std::bind(&BuyNovelClient::buy_novel, this));
}
// 2、创建请求函数
void buy_novel()
{
// 6、编写请求函数
RCLCPP_INFO(this->get_logger(),"去找王五买小说啦!!");
//等待服务端上线
while(!buyclient->wait_for_service(std::chrono::seconds(3))) //若上线则退出循环
{
RCLCPP_INFO(this->get_logger(),"等待卖书服务端上线中...");
}
//(2)设置参数
int money = this->get_parameter("buymoney").as_int();
RCLCPP_INFO(this->get_logger(), "已付款%d", money);
//构造请求数据
auto request = std::make_shared<learning_interfaces1::srv::SellNovel_Request>(); //创建了一个“钱袋”
//request->money = 5; //在“钱袋”里装入了5块钱
request->money = money;
//发送异步请求
buyclient ->async_send_request
(request,std::bind(&BuyNovelClient::buynovel_callback,this,std::placeholders::_1));
}
private:
// 4、声明客户端
rclcpp::Client<learning_interfaces1::srv::SellNovel>::SharedPtr buyclient;
// 9、声明定时器
rclcpp::TimerBase::SharedPtr sendbuy_timer;
// 3、创建请求结果接收回调函数
void buynovel_callback(rclcpp::Client<learning_interfaces1::srv::SellNovel>::SharedFuture response)
{
// 7、编写请求结果接收回调函数
//获取回复的结果
auto buy_result = response.get();
if(buy_result->novels.size() != 0)
RCLCPP_INFO(this->get_logger(),"已收到王五发来的小说共%zu章,准备开读",buy_result->novels.size());
else
RCLCPP_INFO(this->get_logger(),"未收到小说");
//打印出小说内容
for(std::string novels : buy_result->novels)
{
RCLCPP_INFO(this->get_logger(),"在读:%s",novels.c_str());
}
if(buy_result->novels.size() != 0)
RCLCPP_INFO(this->get_logger(), "小说读完了,好期待下面的章节呀!");
}
};
int main(int argc,char** argv)
{
rclcpp::init(argc,argv);
auto node = std::make_shared<BuyNovelClient>("zhang3");
//修改main函数调用请求函数
node->buy_novel();
rclcpp::spin(node);
rclcpp::shutdown();
return 0;
}
四、测试
测试之前,先将三个节点运行起来。
打开三个终端
第一个
colcon build
source install/setup.sh
ros2 run learning_service zhang3_node
第二个
source install/setup.sh
ros2 run learning_service wang5_node
第三个
source install/setup.sh
ros2 run learning_topic li4_node
1.用命令行查看参数
(1)查看参数列表
ros2 param list
(2)查看描述
ros2 param describe /zhang3 buymoney
(3)获取参数值
ros2 param get /zhang3 buymoney
2.修改参数
ros2 param set /zhang3 buymoney 6
ros2 param set /zhang3 buymoney 10
还可以使用rqt修改参数
rqt
打开后点击右上角的刷新,点击zhang3
总结
自用