摘要:這篇文章主要介紹ROS常用工具、ROSPY和ROSCPP常用模塊,完全看完三篇文章,可以說ROS就基本入門,可以自己動手做實驗了。
ROS常用工具
ROS工具的 功能大概有以下幾個方向:仿真、調(diào)試、可視化。這里主要介紹常用工具作用,如何添加模塊,設(shè)置參數(shù)B站都有視頻,這里不會有過多解讀。
gazebo是一種最常用的機器人仿真工具,模擬器,也是目前獨立的開源機器人仿真平臺。gazebo可以進行機器人的動力學仿真,可以模仿機器人常用的傳感器(比如激光雷達、攝像頭、IMU等),也可以加載自定義的環(huán)境和場景。
RViz是可視化工具,是將接收到的信息呈現(xiàn)出來;rviz和gazebo非常相似,但是gazebo實現(xiàn)的是仿真,提供一個虛擬世界,RVIZ實現(xiàn)的是可視化,呈現(xiàn)接收到的信息。
rqt主要作用和RVIZ一致都是可視化,有了它我們可以直觀的看到消息的通信架構(gòu)和流通路徑;
常用命令:
rqt_graph :顯示通信架構(gòu)
rqt_plot :繪制曲線
rqt_console :查看日志
rosbag是一套用于記錄和回放ROS主題的工具,此外還提供代碼API,對包進行操作編寫。
常用命令:cheak 確定一個包是否可以在當前系統(tǒng)中進行,或者是否可以遷移。decompress 壓縮一個或多個包文件。filter 解壓一個或多個包文件。fix 在包文件中修復消息,以便在當前系統(tǒng)中播放。help 獲取相關(guān)命令指示幫助信息info 總結(jié)一個或多個包文件的內(nèi)容。play 以一種時間同步的方式回放一個或多個包文件的內(nèi)容。record 用指定主題的內(nèi)容記錄一個包文件。reindex 重新索引一個或多個包文件。
rosbridge是一個用在ROS系統(tǒng)和其他系統(tǒng)之間的一個功能包,就像是它的名字一樣,起到 一個"橋梁"的作用,使得ros系統(tǒng)和其他系統(tǒng)能夠進行交互.Rosbridge為非ROS程序提供了 一個JSON API,有許多與Rosbridge進行交互的前端,包括一個用于Web瀏覽器交互的 WebSocket服務器。Rosbridge_suite是一個包含Rosbridge的元程序包,用于Rosbridge 的各種前端程序包(如WebSocket程序包)和幫助程序包。
moveit它融合了研究者在運動規(guī)劃、操縱、3D感知、運動學、控制和導航方面的最新進展,為操作 者提供了一個易于使用的平臺,使用它可以開發(fā)先進的機器人應用,也被廣泛應用于工業(yè), 商業(yè),研發(fā)和其他領(lǐng)域。move結(jié)構(gòu)圖如下:
roscpp代碼演示
ROS為我們機器人開發(fā)者提供了不同語言的 接口,比如roscpp是C++語言ROS接口(目前最廣泛應用的ROS客戶端庫,執(zhí)行效率高),rospy是python語言的ROS接口(開發(fā)效率高,通常用在對運行時間沒有太大要求的場合,例如配置、初始化等操作),rosjava是java語言的ROS接口(測試版本) 我們直接調(diào)用它所 提供的函數(shù)就可以實現(xiàn)topic、service等通信功能。
roscpp位于 /opt/ros/kinetic 之下,用C++實現(xiàn)了ROS通信。在ROS中,C++的代碼是通過 catkin這個編譯系統(tǒng)(擴展的CMake)來進行編譯構(gòu)建的。每一個node的節(jié)點功能可能不一樣,但是都包含初始化、銷毀、句柄等操作。
- ROS代碼邏輯整體
常見的ros代碼邏輯包含下面的執(zhí)行步驟:
1.調(diào)用ros::init()函數(shù)初始化節(jié)點的名稱和其他信息
2.創(chuàng)建ros::NodeHandle對象,也就是節(jié)點句柄,用于創(chuàng)建Pub、Sub(NodeHandle就是節(jié)點資源的描述,需要借助“把手”才能操作資源)
3調(diào)用ros::shutdown()手動關(guān)閉節(jié)點(一般是系統(tǒng)自動幫我們完成)。
#include
int main(int argc, char** argv)
{
ros::init(argc, argv, "your_node_name");
ros::NodeHandle nh;
//....節(jié)點功能
//創(chuàng)建話題的publisher
ros::Publisher advertise(const string &topic, uint32_t queue_size, bool latch=false);
//創(chuàng)建話題的subscriber
ros::Subscriber subscribe(const string &topic, uint32_t queue_size, void(*)(M));
//創(chuàng)建服務的server,提供服務
ros::ServiceServer advertiseService(const string &service, bool(*srv_func)(Mreq &, Mre
s &));
//創(chuàng)建服務的client
ros::ServiceClient serviceClient(const string &service_name, bool persistent=false);
//查詢某個參數(shù)的值
bool getParam(const string &key, std::string &s);
bool getParam (const std::string &key, double &d) const;
bool getParam (const std::string &key, int &i) const;
//給參數(shù)賦值
void setParam (const std::string &key, const std::string &s) const;
void setParam (const std::string &key, const char *s) const;
void setParam (const std::string &key, int i) const;
//....
ros::spin();//用于觸發(fā)topic、service的響應隊列
return 0;
}
roscpp的主要部分包括:ros::init() : 解析傳入的ROS參數(shù),創(chuàng)建node第一步需要用到的函數(shù)ros::NodeHandle : 和topic、service、param等交互的公共接口ros::master : 包含從master查詢信息的函數(shù)ros::this_node:包含查詢這個進程(node)的函數(shù)ros::service:包含查詢服務的函數(shù)****ros::param:包含查詢參數(shù)服務器的函數(shù),而不需要用到NodeHandleros::names:包含處理ROS圖資源名稱的函數(shù)
具體可見:http://docs.ros.org/api/roscpp/html/index.html
以上功能可以分為以下幾類:Initialization and Shutdown 初始與關(guān)閉Topics 話題Services 服務Parameter Server 參數(shù)服務器Timers 定時器NodeHandles 節(jié)點句柄Callbacks and Spinning 回調(diào)和自旋(或者翻譯叫輪詢?)Logging 日志Names and Node Information 名稱管理Time 時鐘Exception 異常
-
回調(diào)函數(shù)與spin()方法
CallBack回調(diào)函數(shù)與ros::spin() 方法需要配合使用,當消息傳來時,只指定回調(diào)函數(shù),系統(tǒng)不會自動觸發(fā),必須要 ros::spin() 或 者 ros::spinOnce() 才能真正使回調(diào)函數(shù)生效。 處理流程:回調(diào)函數(shù)一般作為參數(shù)傳到另外一個函數(shù)(一般是函數(shù)指針),當消息message到達時,先會把消息放到一個隊列中,當有spin函數(shù)執(zhí)行時,就會處理消息隊列隊首的信息。spin具體的處理方法可以分成阻塞/非阻塞,單線程/多線程兩種。
spin方法 阻塞 線程 ros::spin() 阻塞 單線程 ros::spinOnce() 非阻塞 單線程 ros::MultiTreadedSpin() 阻塞 多線程 ros::AsyncMultiThreadedSpin() 非阻塞 多線程 -
ROS節(jié)點編寫
基本流程,首先創(chuàng)建一個工作空間workplace,然后根據(jù)實際需要創(chuàng)建相應的包package,編寫相應的需求文件,如源文件;根據(jù)編譯運行需要,補充CMakeLists.txt、package.xml相應說明,如添加依賴,查找相關(guān)包,運行所需要的包,消息類型等等。
mkdir -p xxx_ws //創(chuàng)建工作空間 catkin_make //編譯工作空間 //打開.bashrc 設(shè)置xxx_ws工作空間的環(huán)境變量 catkin_create_pkg xxxx(包) xx(依賴) //創(chuàng)建包
- 編寫一個talker的node
在工作空間的src/目錄下,第1步,創(chuàng)建一個talker的包study:$ catkin_create_pkg study roscpp第2步,打開vcode(或者其他ide),study/src,創(chuàng)建源文件study_node.cpp,代碼如下:
#include"ros/ros.h"
#include"std_msgs/String.h"
#include
//編寫一個node并發(fā)布出來
int main(int argc,char **argv){
ros::init(argc,argv,"study_talker");//定義node的屬性
ros::NodeHandle n;//ros提供的一個類,可以實例化publisher,進行發(fā)布數(shù)據(jù)
ros::Publisher study_pub=n.advertise
第3步,設(shè)置CMakeLists.txt&package.xmlCMakeLists.txt:
find_package(catkin REQUIRED COMPONENTS
roscpp
std_msgs
)//告訴系統(tǒng)編譯本包時,需要找到這兩個包
catkin_package(
# INCLUDE_DIRS include
# LIBRARIES study
CATKIN_DEPENDS roscpp std_msgs
# DEPENDS system_lib
)//聲明依賴本包同時需要里面這兩個ros包
add_executable(${PROJECT_NAME}_node src/study_node.cpp)//編譯本包生成的可執(zhí)行文件
add_dependencies(${PROJECT_NAME}_node ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})//鏈接可執(zhí)行文件和依賴庫
//一般情況而已,CMakeLists.txt是創(chuàng)建包同時,系統(tǒng)自動生成的,然后,我們需要的工作,一般情況就是把上面基本地方去掉#號就行了(目的告訴系統(tǒng),關(guān)于該包,在哪,依賴是啥)
package.xml:
roscppclass="hljs-name"build_depend>
std_msgsclass="hljs-name"build_depend>
roscppclass="hljs-name"exec_depend>
std_msgsclass="hljs-name"exec_depend>
//主要修改類似樣式,當然,本例子比較簡單,系統(tǒng)生成的,不需要做其他修改,但是,如果節(jié)點添加新的依賴,需要在這些地方添加相應的包
第4步,編譯
$ catkin_make #注意在要做工作空間的一級目錄下使用該指令
第5步,驗證,終端運行
$ roscore & #后臺運行一個ROS master
$ rosrun study study_node & #后臺運行包名+節(jié)點名
$ rostopic list #
/study_topic //表示定義的topic正常發(fā)布
/rosout
/rosout_agg
$ rostopic echo #查看study_topic
data: "hello study world!2360"//表示發(fā)布成功
---
data: "hello study world!2361"
這時,從零開始創(chuàng)建的talker節(jié)點node,成功創(chuàng)建完成
- 編寫一個listener的node
在工作空間的src/目錄下,第1步,創(chuàng)建一個listener的包study_listen:
$ catkin_create_pkg study_listen roscpp
第2步,study_listen/src,創(chuàng)建源文件study_listen_node.cpp
#include"ros/ros.h"
#include"std_msgs/String.h"
//創(chuàng)建一個listener的node
void studyCallback(const std_msgs::String::ConstPtr& msg){
//回調(diào)函數(shù)一定是要求是無返回類型
ROS_INFO("I can see you again,%s",msg->data.c_str());
}
int main(int argc,char ** argv){
ros::init(argc,argv,"study_listener");//初始化這么一個node
ros::NodeHandle n;//命名空間
ros::Subscriber sub=n.subscribe("study_topic",10,studyCallback);
//表示聆聽study_topic這個主題,每次聽到就會啟動回調(diào)函數(shù),這里的10也表示一個緩沖數(shù)量,多了,前面的會被是放掉
//這里一定要注意,聆聽的topic一定要和發(fā)布的topic的名稱對應上,否則,是沒辦法接收的
ros::spin();
return 0;
}
-
仿真
+關(guān)注
關(guān)注
50文章
4087瀏覽量
133651 -
調(diào)試
+關(guān)注
關(guān)注
7文章
578瀏覽量
33957 -
ROS
+關(guān)注
關(guān)注
1文章
278瀏覽量
17019
發(fā)布評論請先 登錄
相關(guān)推薦
評論