日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

ROS:参数服务器通信

發布時間:2024/1/18 编程问答 97 豆豆
生活随笔 收集整理的這篇文章主要介紹了 ROS:参数服务器通信 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

為什么需要

在機器人開發中,會有很多參數和設置可以后期需要調整的,如果都放到源碼里很難實現動態修改和管理,ROS2為了解決這一問題,提出了參數這一通信機制。

是什么

如何理解“參數”?

  • ROS2的參數就是節點的設置
  • 參數類似于ROS中的全局變量,由ROS Master進行管理,其通信機制較為簡單,不涉及TCP/UDP的通信。

參數服務器是一種特殊的“通信方式”。特殊點在于參數服務器是節點存儲參數的地方、用于配置參數、全局共享參數。

  • 參數服務器使用互聯網傳輸,在節點管理器中運行,實現整個通信過程
  • 參數服務器,作為ROS中另外一種數據傳輸方式,有別于topic和service,它更加靜態。
  • 參數服務器維護者一個數據字典,字典里存儲著各種參數和配置
    • 參數服務器在ROS中主要用于實現不同節點之間的數據共享。一般用于存儲一些多節點共享的數據,類似于全局變量。
    • 參數服務器相當于是獨立于所有節點的一個公共容器,可以將數據存儲在該容器中,被不同的節點調用,當然不同的節點也可以往其中存儲數據。

維護方式

參數服務器的維護方式非常的簡單靈活,總的來講有三種方式:

  • 命令行維護
  • launch文件內讀寫
  • node源碼

命令行維護

使用命令行來維護參數服務器,主要使用rosparam語句來進行操作的各種命令,如下表:

ROS1:rosparam 命令作用
rosparam set param_key param_value設置參數
rosparam get param_key顯示參數
rosparam load file_name從文件加載參數
rosparam dump file_name保存參數到文件
rosparam delete刪除參數
rosparam list列出參數名稱

load&&dump文件

load和dump文件需要遵守YAML格式,一般格式如下:

key : value

具體示例如下:

name:'Zhangsan' age:20 gender:'M' score{Chinese:80,Math:90} score_history:[85,82,88,90]

一般格式如下:

launch文件內讀寫

launch文件中有很多標簽,而與參數服務器相關的標簽只有兩個,一個是< param>,另一個是< rosparam>

node源碼

除了上述最常用的兩種讀寫參數服務器的方法,還有一種就是修改ROS的源碼,也就是利用API來對參數服務器進行操作。具體內容我們學習完后面章節再進行介紹。

ROS2:體驗一下

(1)運行小烏龜模擬器節點和小烏龜控制節點

# 終端一 ros2 run turtlesim turtlesim_node# 終端二 ros2 run turtlesim turtle_teleop_key

(2)查看參數

  • 查看節點有哪些參數(設置)
ros2 param list

  • 看參數的詳情信息:參數的名字,參數的描述,參數的類型,還有對參數的約束,最大值最小值等。
# ---- 語法-------- ros2 param describe <node_name> <param_name># ------ 舉例 --- ros2 param describe /turtlesim background_b

  • 獲取參數名
param list
  • 獲取參數值
ros2 param get /turtlesim background_b

  • 設置參數值:注意這里只是臨時修改
# ------------語法 ros2 param set <node_name> <parameter_name> <value># ---------- 舉個例子 ros2 param set /turtlesim background_r 44 ros2 param set /turtlesim background_g 156 ros2 param set /turtlesim background_b 10
  • 把參數存起來:相當去把當前的參數值拍一張快照,然后保存下來,后面可以用于恢復參數到當前的數值。
# ------------語法 ros2 param dump <node_name># ---------- 舉個例子 ros2 param dump /turtlesim # 文件被保存成了yaml格式,用cat指令看一看 文件被保存成了yaml格式,用cat指令看一看# 恢復參數:# 方法一:# 我們Ctrl+C關閉烏龜模擬器,然后再重新運行。ros2 run turtlesim turtlesim_node# 著通過param的load的方法把參數值恢復成我們之前存儲的。ros2 param load /turtlesim ./turtlesim.yaml# 方法二:啟動節點時加載參數快照# 語法:ros2 run <package_name> <executable_name> --ros-args --params-file <file_name># 先關閉烏龜,然后重新運行ros2 run turtlesim turtlesim_node --ros-args --params-file ./turtlesim.yaml

三個角色

  • ROS Master (管理者):管理者作為一個公共的容器保存數據
  • Talker (參數設置者):參數設置者往容器中存儲數據
  • Listener (參數調用者): 參數調用者讀取容器中所需的數據

建立流程

  • step1:
    • 參數設置者使用RPC向參數服務器發送參數(包括參數名與參數值)
    • ROS Master 將參數保存到參數列表中。
  • step2:
    • 參數調用者使用RPC向參數服務器發送參數查找請求,請求中包含要查找的參數名。
  • step3:
    • ROS Master 根據步驟2請求提供的參數名查找參數值,并使用RPC將查詢結果發送給參數調用者。

參數組成成分

ROS2參數是由鍵值對組成的.

  • 名字的數據類型是字符串
  • 值的數據類型可以是:
    • bool 和bool[],布爾類型用來表示開關,比如我們可以控制雷達控制節點,開始掃描和停止掃描。
    • int64 和int64[],整形表示一個數字,含義可以自己來定義
    • float64 和float64[],浮點型,可以表示小數類型的參數值
    • string 和string[],字符串,可以用來表示雷達控制節點中真實雷達的ip地址
    • byte[],字節數組,這個可以用來表示圖片,點云數據等信息

代碼實現

ROS2將日志分為五個級別,在RCLCPP中通過不同的宏可以實現不同日志級別日志的打印,例程如下

RCLCPP_DEBUG(this->get_logger(), "我是DEBUG級別的日志,我被打印出來了!"); RCLCPP_INFO(this->get_logger(), "我是INFO級別的日志,我被打印出來了!"); RCLCPP_WARN(this->get_logger(), "我是WARN級別的日志,我被打印出來了!"); RCLCPP_ERROR(this->get_logger(), "我是ERROR級別的日志,我被打印出來了!"); RCLCPP_FATAL(this->get_logger(), "我是FATAL級別的日志,我被打印出來了!");

有時候日志太多,會讓人眼花繚亂找不到重要信息,所以我們需要對日志的級別進行過濾,比如只看INFO以上級別的,ROS2中可以通過已有的API設置日志的級別,RCLCPP中API如下:

this->get_logger().set_level(log_level);

目標:聲明參數并實現動態修改打印的日志級別功能

RCLCPP實現

創建功能包和節點

mkdir -p chapt4/chapt4_ws/ ros2 pkg create example_parameters_rclcpp --build-type ament_cmake --dependencies rclcpp --destination-directory src --node-name parameters_basic --maintainer-name "fishros" --maintainer-email "fishros@foxmail.com"

parameters_basic.cpp

#include <chrono> #include "rclcpp/rclcpp.hpp"class ParametersBasicNode : public rclcpp::Node {public:explicit ParametersBasicNode(std::string name) : Node(name) {RCLCPP_INFO(this->get_logger(), "節點已啟動:%s.", name.c_str());}private: };int main(int argc, char** argv) {rclcpp::init(argc, argv);/*產生一個的節點*/auto node = std::make_shared<ParametersBasicNode>("parameters_basic");/* 運行節點,并檢測退出信號*/rclcpp::spin(node);rclcpp::shutdown();return 0; }

構建測試:

colcon build --packages-select example_parameters_rclcpp source install/setup.bash ros2 run example_parameters_rclcpp parameters_basic

參數API

在RCLCPP的API中,關于參數相關的函數比較多些,但都是圍繞參數獲取、參數設置、參數描述、列出參數、添加和移除參數回調事件。

使用參數控制節點日志級別

#include <chrono> #include "rclcpp/rclcpp.hpp" /*# declare_parameter 聲明和初始化一個參數# describe_parameter(name) 通過參數名字獲取參數的描述# get_parameter 通過參數名字獲取一個參數# set_parameter 設置參數的值 */ class ParametersBasicNode : public rclcpp::Node {public:// 構造函數,有一個參數為節點名稱explicit ParametersBasicNode(std::string name) : Node(name) {RCLCPP_INFO(this->get_logger(), "節點已啟動:%s.", name.c_str());this->declare_parameter("rcl_log_level", 0); /*聲明參數*/this->get_parameter("rcl_log_level", log_level); /*獲取參數*//*設置日志級別*/this->get_logger().set_level((rclcpp::Logger::Level)log_level);using namespace std::literals::chrono_literals;timer_ = this->create_wall_timer(500ms, std::bind(&ParametersBasicNode::timer_callback, this));}private:int log_level;rclcpp::TimerBase::SharedPtr timer_;void timer_callback() {this->get_parameter("rcl_log_level", log_level); /*獲取參數*//*設置日志級別*/this->get_logger().set_level((rclcpp::Logger::Level)log_level);std::cout<<"======================================================"<<std::endl;RCLCPP_DEBUG(this->get_logger(), "我是DEBUG級別的日志,我被打印出來了!");RCLCPP_INFO(this->get_logger(), "我是INFO級別的日志,我被打印出來了!");RCLCPP_WARN(this->get_logger(), "我是WARN級別的日志,我被打印出來了!");RCLCPP_ERROR(this->get_logger(), "我是ERROR級別的日志,我被打印出來了!");RCLCPP_FATAL(this->get_logger(), "我是FATAL級別的日志,我被打印出來了!");} };int main(int argc, char** argv) {rclcpp::init(argc, argv);/*產生一個的節點*/auto node = std::make_shared<ParametersBasicNode>("parameters_basic");/* 運行節點,并檢測退出信號*/rclcpp::spin(node);rclcpp::shutdown();return 0; }

上面set_level,設置日志級別,ROS2的日志級別定義在文件/opt/ros/humble/include/rcutils/rcutils/logging.h的167-175行

/// The severity levels of log messages / loggers. enum RCUTILS_LOG_SEVERITY {RCUTILS_LOG_SEVERITY_UNSET = 0, ///< The unset log levelRCUTILS_LOG_SEVERITY_DEBUG = 10, ///< The debug log levelRCUTILS_LOG_SEVERITY_INFO = 20, ///< The info log levelRCUTILS_LOG_SEVERITY_WARN = 30, ///< The warn log levelRCUTILS_LOG_SEVERITY_ERROR = 40, ///< The error log levelRCUTILS_LOG_SEVERITY_FATAL = 50, ///< The fatal log level };

編譯測試

colcon build --packages-select example_parameters_rclcpp source install/setup.bash ros2 run example_parameters_rclcpp parameters_basic

運行后你會發現DEBUG級別的日志并沒有被打印出來,原因在于我們將節點的日志級別設置為了0,0對應的日志級別為RCUTILS_LOG_SEVERITY_UNSET即未設置使用默認級別,節點默認的日志級別就是INFO級別的,所以只能打印INFO以上的日志信息。

運行節點的時候可以指定參數的值,我們嘗試將log_level的值改成10即DEBUG級別。

ros2 run example_parameters_rclcpp parameters_basic --ros-args -p rcl_log_level:=10

除了在節點運行前通過CLI傳遞參數,在運動的過程中也可以動態的修改參數

#查看參數列表 ros2 param list #設置參數級別 ros2 param set /parameters_basic rcl_log_level 10

補充

上面我們通過參數實現了動態控制節點日志級別的功能,其實像這樣的功能ROS2早已為我們準備好了,在運行任意節點時候可以通過CLI傳遞日志級別配置。

ros2 run package-name node-name --ros-args --log-level debug

除了命令行設置參數和查看日志,通過rqt也可以可視化設置和查看

總結

以上是生活随笔為你收集整理的ROS:参数服务器通信的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。