機器人操作系統入門(六)roscpp客戶端庫


參考資料:

https://www.icourse163.org/course/ISCAS-1002580008?tid=1003713012  //中國大學MOOC

https://www.bilibili.com/video/av23401751  //B站

《ROS操作系統入門講義》PDF下載

鏈接:https://pan.baidu.com/s/1OCja2WLDRnjYXMrpnZ3-sQ 
提取碼:mziy

第六章 roscpp

一、ROS支持的客戶端庫和整體的包結構分布

二、roscpp:位於/opt/ros/kinetic  // #include<ros/ros.h>

1. 主要部分

(1)ros::init():解析傳入的ROS參數,創建node第一步需要用到的函數  //可以為node命名

(2)ros::NodeHandle:和topic、service、param等交互的公共接口  //類,需要創建句柄對象

(3)ros::master:包含從master查詢信息的函數  //命名空間,無需創建對象

(4)ros::this_node:包含查詢這個進程(node)的函數

(5)ros::service:包含查詢服務的函數

(6)ros::param:包含查詢參數服務器的函數,而不需要用到NodeHandle

(7)ros::names:包含處理ROS圖資源名稱的函數

2. 按功能分類

  • Initialization and Shutdown 初始與關閉
  • Topics 話題
  • Services 服務
  • Parameter Server 參數服務器
  • Timers 定時器
  • NodeHandles 節點句柄
  • Callbacks and Spinning 回調和自旋(輪詢
  • Logging 日志
  • Names and Node Information 名稱管理
  • Time 時鍾
  • Exception 異常

三、節點初始化、關閉以及句柄NodeHandle

1. 初始化

(1)ros::init():初始化節點的名稱和其他信息

(2)ros::NodeHandle對象:節點句柄,用來創建Publisher、Subscriber等

注:句柄NodeHandle是對節點資源的描述,通過它對節點進行操作,如為程序提供服務、監聽某個topic上的消息、訪問和修改param等

2. 關閉節點

(1)終端輸入"Ctrl + C"  //自動觸發SIGINT句柄關閉進程

(2)調用ros::shutdown()  //手動關閉節點

注:常用執行流程如下  // 啟動節點+獲取句柄

3. NodeHandle類的常用成員函數  //

四、基於roscpp的topic通信

(1)功能:自定義一個類型為gps的消息(包括位置x,y和工作狀態state信息),一個node以一定頻率發布模擬的gps消息,另一個node接收並處理,算出到原點的距離

(2)自定義gps.msg消息  //類似於C語言中的結構體

string state  #工作狀態

float32 x  #x坐標

float32 y  #y坐標

(3)修改CMakeLists.txt和package.xml  //編譯自定義消息

CMakeLists.txt:

package.xml:

  <build_depend>message_generation</build_depend>

  <run_depend>message_runtime</run_depend>

注:

  • 回到工作空間編譯完成后,會在devel路徑下自動生成gps.msg對應的頭文件,其中定義了topic_demo::gps類
  • 通過 #include<topic_demo/gps.h>,使用自定義消息類型
  • topic_demo::gps mygpsmsg;
    mygpsmsg.x = 1.6;
    mygpsmsg.y = 5.5;
    mygpsmsg.state = "working";

(4)消息發布節點 talker.cpp  //發布gps_info話題

(5)消息訂閱節點 listener.cpp

注:

  • 通過定義回調函數,為gps_info話題預先准備一個回調函數,接收到消息時被觸發執行
  • 回調函數作為參數被傳入到了另一個函數中(在本例中傳遞的是函數指針),在未來某個時刻(當有新的message到達),就會立即執行

(6)修改CMakeList.txt

(7)spin調用方式  //多線程用於分別處理不同數據

五、基於roscpp的service通信

(1)自定義服務文件Greeting.srv

string name #短橫線上邊部分是服務請求的數據

int32 age

--- #短橫線下面是服務回傳的內容。

string feedback

注:相當於嵌套了請求和響應兩個結構體

(2)修改CMakeList.txt:add_service_files(FILES Greeting.srv)

通過#include <service_demo/Greeting.h>進行調用

service_demo::Greeting grt; //grt分為grt.request和grt.response兩部分

grt.request.name = "HAN"; //不能用grt.name或者grt.age來訪問

grt.request.age = "20";

(3)服務提供節點 server.cpp

注:

  • 服務的處理操作由handle_function()函數確定,輸入參數為Greeting的Request和Response兩部分,對對Requst數據進行需要的操作,將結果寫入到Response中
  • 返回值為bool值,用於判斷服務是否調用成功  //不輸出Response

(4)服務請求節點 client.cpp

注:CMakeList.txt和package.xml的修改和topic_demo類似

六、基於roscpp的參數服務器設置

(1)兩種方式

  • ros::param命名空間
  • ros::NodeHandle節點句柄

(2)實際項目中對參數的設置通常都不在程序中,而是利用launch文件  //launch文件可以方便地修改參數,而寫成代碼之后,修改參數必須重新編譯

(3)命名空間對param的影響  // ros::NodeHandle n; 和 ros::NodeHandle nh("~") 的區別

假設參數定義如下:

那么 name_demo.cpp文件如下:

輸出:

可見:

  • n為全局命名空間句柄,當訪問節點私有命名空間內的參數時,需要添加節點名
  • nh為局部命名空間句柄,當訪問全局命名空間的參數時,需要添加全局命名空間 /

七、時鍾

(1)兩種時間表示方法  //均由秒和納秒組成:int32 sec;int32 nsec

  • ros::Time  //某個時刻,#include<ros/time.h>
  • ros::Duration  //某個時段,#include<ros/duration.h>

用法示例:

  • ros::Time begin = ros::Time::now();  //獲取當前時間
  • ros::Time at_some_time1(5,20000000);  //5.2s
  • ros::Time at_some_time2(5.2)  //同上,重載了float類型和兩個uint類型的構造函數
  • ros::Duration one_hour(60*60,0);  //1h
  • double secs1 = at_some_time1.toSec();  //將Time轉為double型時間
  • double secs2 = one_hour.toSec();  //將Duration轉為double型時間

時刻Time和Duration時長之間存在加減運算

  • ros::Time t1 = ros::Time::now() - ros::Duration(5.5);  //t1是5.5s前的時刻,Time加減Duration返回都是Time
  • ros::Time t2 = ros::Time::now() + ros::Duration(3.3);  //t2是當前時刻往后推3.3s的時刻
  • ros::Duration d1 = t2 - t1;  //從t1到t2的時長,兩個Time相減返回Duration類型
  • ros::Duration d2 = d1 -ros::Duration(0,300);  //兩個Duration相減,還是Duration

注:不存在Time+Time

(2)休眠功能sleep

注:Rate的功能是指定一個頻率,讓某些動作按照這個頻率來循環執行

(3)定時器Timer:與Rate類似,通過設定回調函數和觸發時間實現某些動作的反復執行,創建方法類似topic中的subscriber

八、日志和異常

(1)日志log

  • 每個節點都會把日志信息發送到統一的話題 /rosout
  • rosout本身也是一個節點,負責日志的記錄

(2)日志的輸出:#include<ros/console.h>

五個級別:

  • DEBUG:ROS_DEBUG("The velocity is %f", vel);
  • INFO:ROS_INFO
  • WARN:ROS_WARN("Warn: the use is deprecated.");
  • ERROR:ROS_ERROR
  • FATAL:ROS_FATAL("Cannot start this node.");

(3)異常Exception  //針對兩類錯誤

  • ros::InvalidNodeNameException  //當無效的基礎名稱傳給ros::init(),通常是名稱中有/,就會觸發
  • ros::InvalidNameExcaption  //當無效名稱傳給了roscpp

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM