大家好,關(guān)于機(jī)器人操作系統(tǒng)ROS的安裝,很多文章都寫的非常詳細(xì),我也在這些材料的幫助下,在VMware上安裝了Ubuntu14.04以及對(duì)應(yīng)的ROS Indigo,詳情見Ubuntu14.04安裝和配置ROS Indigo。但是,著重強(qiáng)調(diào)一點(diǎn),不同的Ubuntu系統(tǒng)版本對(duì)應(yīng)不同的ROS版本,因此安裝中的命令語句有差異,請(qǐng)大家務(wù)必先明確自己的開發(fā)環(huán)境。接下來,就開始ROS的學(xué)習(xí)之路!
ROS入門,非常推薦通過官網(wǎng)ROS Tutorials或者ROS中文網(wǎng)站學(xué)習(xí)(更加推薦英文網(wǎng)站)的初級(jí)教程(Beginner Level)學(xué)習(xí)。有一些ROS書籍,其實(shí)里面很多內(nèi)容是對(duì)官網(wǎng)的翻譯,但是這些書籍可能的局限性是:1)ROS版本問題;2)編程語言,有的書只提供C++代碼,有些只提供Python。但是在官網(wǎng),Python和C++版本的tutorials均有,選擇性更強(qiáng)。
本文主要是了解ROS的內(nèi)部構(gòu)成、文件夾結(jié)構(gòu)以及工作所需的核心文件。
ROS系統(tǒng)的架構(gòu)主要被設(shè)計(jì)和劃分為三部分,每一部分代表一個(gè)層級(jí)的概念:文件系統(tǒng)級(jí)(The filesystem level)、計(jì)算圖級(jí)(The computation graph level)、開源社區(qū)級(jí)(The community level)
一、ROS文件系統(tǒng)級(jí)
如圖1所示:
功能包-功能包是ROS中軟件組織的基本形式。一個(gè)功能包具有用于創(chuàng)建ROS程序的最小結(jié)構(gòu)和最少內(nèi)容。它可以包含ROS運(yùn)行的進(jìn)程(節(jié)點(diǎn))、配置文件等;
功能包清單-功能包清單提供關(guān)于功能包、許可信息、依賴關(guān)系、編譯標(biāo)志等的信息。一個(gè)包的清單有一個(gè)名為package.xml的文件管理;
綜合功能包-將幾個(gè)具有某些功能的功能包組織在一起,就獲得了一個(gè)綜合功能包(Stack)。
二、ROS計(jì)算圖級(jí)
ROS會(huì)創(chuàng)建一個(gè)連接到所有進(jìn)程的網(wǎng)絡(luò)。在系統(tǒng)中的任何節(jié)點(diǎn)都可以訪問此網(wǎng)絡(luò),并通過該網(wǎng)絡(luò)與其他節(jié)點(diǎn)交互,獲取其他節(jié)點(diǎn)發(fā)布的信息,并且將自身數(shù)據(jù)發(fā)布到網(wǎng)絡(luò)上。如圖2所示:
節(jié)點(diǎn)-節(jié)點(diǎn)是主要的計(jì)算執(zhí)行進(jìn)程;
節(jié)點(diǎn)管理器-節(jié)點(diǎn)管理器用于節(jié)點(diǎn)的名稱注冊(cè)、查找、設(shè)置節(jié)點(diǎn)間通信等;
參數(shù)服務(wù)器-參數(shù)服務(wù)器能夠使數(shù)據(jù)通過一個(gè)關(guān)鍵詞存儲(chǔ)在一個(gè)系統(tǒng)的核心位置;
消息-消息是節(jié)點(diǎn)之間溝通的一種方式;
主題-每個(gè)消息都必須有一個(gè)名稱來被ROS網(wǎng)絡(luò)路由。每一條消息都要發(fā)布到相應(yīng)的主題。當(dāng)一個(gè)節(jié)點(diǎn)發(fā)送數(shù)據(jù)時(shí),我們就說該節(jié)點(diǎn)正在向主題發(fā)布消息。節(jié)點(diǎn)可以通過訂閱某個(gè)主題,接受來自其他節(jié)點(diǎn)的消息。一個(gè)節(jié)點(diǎn)可以訂閱一個(gè)主題,而不需要該節(jié)點(diǎn)同時(shí)發(fā)布該主題。這就保證了消息的發(fā)布者和訂閱者間解耦。主題的名稱是獨(dú)一無二的,否則在同名主題之間的消息路由就會(huì)發(fā)生錯(cuò)誤。
服務(wù)-如果需要直接與某個(gè)節(jié)點(diǎn)進(jìn)行交互request/response,此時(shí)不能通過Topic,而需要服務(wù)。服務(wù)必須有唯一的名稱,當(dāng)一個(gè)節(jié)點(diǎn)提供某個(gè)服務(wù)時(shí),所有的幾點(diǎn)都可以通過使用ROS客戶端邊寫的代碼與它通信。
消息記錄包-消息記錄包是一種用于保存和回放ROS消息數(shù)據(jù)的文件格式。消息記錄包是一種用于存儲(chǔ)數(shù)據(jù)的主要機(jī)制,它能夠獲取并記錄各種難以收集的傳感器數(shù)據(jù)。可以通過消息記錄包反復(fù)獲取實(shí)驗(yàn)數(shù)據(jù),進(jìn)行必要的開發(fā)和算法測(cè)試。
三、官網(wǎng)初級(jí)文檔-文件系統(tǒng)架構(gòu)學(xué)習(xí)(我的ros版本是indigo)
1、創(chuàng)建工作空間(工作空間可以簡(jiǎn)單理解為一個(gè)項(xiàng)目文件夾)
1)查看ROS正在使用的工作空間
echo $ROS_PACKAGE_PATH
顯示:/opt/ros/indigo/share:/opt/ros/indigo/stacks
2)創(chuàng)建工作空間
$ mkdir -p ~/softdemo/catkin_ws/src ? ? ? #mkdir->在當(dāng)前目錄下創(chuàng)建子目錄
$ cd ~/softdemo/catkin_ws/src
$ catkin_init_workspace ? ? ?
3)編譯工作空間
$ cd ~/softdemo/catkin_ws/ ? ? ? ??
$ catkin_make? ? #編譯必須在catkin_ws文件夾下,如果在任何src文件夾下的功能包編譯,都會(huì) ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?報(bào)錯(cuò)
4)完成配置
$ source devel/setup.bash
至此,文件結(jié)構(gòu)如下:
~softdemo->catkin_ws->build? devel? src
2、創(chuàng)建ROS功能包和綜合功能包
$ cd ~/catkin_ws/src
創(chuàng)建功能包beginner_tutorials,并且建立依賴,可以是rospy(基于Python)或者roscpp(基于C++)(Now use the catkin_create_pkg script to create a new package called 'beginner_tutorials' which depends on std_msgs, roscpp, and rospy:)
$ catkin_create_pkg beginner_tutorials std_msgs rospy roscpp
3、編譯ROS功能包(主要是代碼編譯)
$ cd ~/catkin_ws/
$ catkin_make
備注:必須在工作空間文件夾(catkin_ws)運(yùn)行catkin_make,否則報(bào)錯(cuò)
4、ROS節(jié)點(diǎn)
使用某個(gè)節(jié)點(diǎn)時(shí),只需要寫出包名和節(jié)點(diǎn)名字就可以調(diào)用節(jié)點(diǎn),不需要寫路徑
$ rosrun [package_name] [node_name]
修改節(jié)點(diǎn)的名字可以直接在命令行進(jìn)行(同時(shí)可以運(yùn)行該幾點(diǎn)做其他任務(wù)):
$ rosrun turtlesim turtlesim_node __name:=my_turtle
展示當(dāng)前運(yùn)行的節(jié)點(diǎn):
$ rosnode list
5、ROS Topic使用
舉例:調(diào)用小烏龜節(jié)點(diǎn),然后點(diǎn)擊鍵盤,使得烏龜根據(jù)鍵盤上下左右按鍵來運(yùn)動(dòng)
1)調(diào)用小烏龜節(jié)點(diǎn),彈出如圖3所示的界面(turtlesim是功能包)
$ rosrun turtlesim turtlesim_node
2)在新的終端,調(diào)用鍵盤遙操作(keyboard teleoperation)節(jié)點(diǎn),小烏龜動(dòng)起來了,如圖4
$ rosrun turtlesim turtle_teleop_key
3)之所以上面的小烏龜能夠響應(yīng)鍵盤鍵,出現(xiàn)圖4的運(yùn)動(dòng)軌跡,就是因?yàn)楣?jié)點(diǎn)turtlesim_node和turtle_teleop_key通過topic進(jìn)行了通信(turtle_teleop_key is publishing the key strokes on a topic, while turtlesim subscribes to the same topic to receive the key strokes)
4)為了展示它們間的關(guān)系,調(diào)用rqt_graph,結(jié)果見圖5
$ rosrun rqt_graph rqt_graph
圖5表明當(dāng)前topic名稱是:/turtle1/cmd_vel
5)基于rostopic tool 可以從ROS Topics獲取信息
$ rostopic -h
rostopic bw? ? display bandwidth used by topic
rostopic echo? print messages to screen
rostopic hz? ? display publishing rate of topic
rostopic list? print information about active topics
rostopic pub? ? publish data to topic
rostopic type? print topic type
比如:$ rostopic echo /turtle1/cmd_vel
6、ROS Message
ROS Topic通信是通過節(jié)點(diǎn)間發(fā)送message來實(shí)現(xiàn)的,ROS里面要求節(jié)點(diǎn)間發(fā)送message的類型必須一致(Communication on topics happens by sending ROS messages between nodes. For the publisher (turtle_teleop_key) and subscriber (turtlesim_node) to communicate, the publisher and subscriber must send and receive the same type of message.)ROS里,通過rostopic type來決定message的type:$ rostopic type [topic]
比如上面提到的topic:/turtle1/cmd_vel,其對(duì)應(yīng)的消息類型為:
$ rostopic type /turtle1/cmd_vel
結(jié)果為:geometry_msgs/Twist
進(jìn)一步獲取message的詳細(xì)信息:
$ rosmsg show geometry_msgs/Twist
得到:
geometry_msgs/Vector3 linear
float64 x
float64 y
float64 z
geometry_msgs/Vector3 angular
float64 x
float64 y
float64 z
7、接下來基于以上內(nèi)容,通過給節(jié)點(diǎn)turtlesim_node發(fā)信息,來控制其運(yùn)動(dòng)。
1)使用rostopic pub來發(fā)布當(dāng)前topic的信息:rostopic pub [topic] [msg_type] [args]
$ rostopic pub -1 /turtle1/cmd_vel geometry_msgs/Twist -- '[2.0, 0.0, 0.0]' '[0.0, 0.0, 1.8]'
以上命令結(jié)果見下圖6
2)該指令的作用下,發(fā)現(xiàn)小烏龜運(yùn)動(dòng)了一下就停止了。怎樣讓小烏龜一直運(yùn)動(dòng)下去,使用‘rostopic pub -r’指令
$ rostopic pub /turtle1/cmd_vel geometry_msgs/Twist -r 1 -- '[2.0, 0.0, 0.0]' '[0.0, 0.0, -1.8]'
該語句仿真效果見下圖,在實(shí)際中,小烏龜一直沿著這個(gè)圓圈運(yùn)動(dòng),直到強(qiáng)制跳出該語句
3)獲取信息發(fā)布的頻率:rostopic hz [topic]
$ rostopic hz /turtle1/pose
subscribed to [/turtle1/pose]
average rate: 59.354
min: 0.005s max: 0.027s std dev: 0.00284s window: 58
average rate: 59.459
min: 0.005s max: 0.027s std dev: 0.00271s window: 118
average rate: 59.539
min: 0.004s max: 0.030s std dev: 0.00339s window: 177
average rate: 59.492
min: 0.004s max: 0.030s std dev: 0.00380s window: 237
average rate: 59.463
min: 0.004s max: 0.030s std dev: 0.00380s window: 290
以上數(shù)據(jù)表明發(fā)布信息的頻率是60Hz
8、ROS services
1)節(jié)點(diǎn)(node)之間通信的另一種方式就是通過ROS services。services允許節(jié)點(diǎn)間發(fā)request,收response。這一過程是通過rosservice模塊來實(shí)現(xiàn)的
Topics上可以使用的語句包括:
rosservice list? ? ? ? print information about active services
rosservice call? ? ? ? call the service with the provided args
rosservice type? ? ? ? print service type
rosservice find? ? ? ? find services by service type
rosservice uri? ? ? ? ? print service ROSRPC uri
2)通過rosparam可以獲取或者處理ROS Parameter Server上的數(shù)據(jù)
rosparam set? ? ? ? ? ? set parameter
rosparam get? ? ? ? ? ? get parameter
rosparam load? ? ? ? ? load parameters from file
rosparam dump? ? ? ? ? dump parameters to file
rosparam delete? ? ? ? delete parameter
rosparam list? ? ? ? ? list parameter names
rosparam 使用 YAML markup language,文件的合適是.yaml,比如:$ rosparam dump params.yaml
9、ROS調(diào)試控制臺(tái)和日志記錄(rqt_console and rqt_logger_level)
rqt_console->顯示節(jié)點(diǎn)的輸出(rqt_console attaches to ROS's logging framework to display output from nodes)
rqt_logger_level->改變節(jié)點(diǎn)日志的冗長(zhǎng)級(jí)別(rqt_logger_level allows us to change the verbosity level (DEBUG, WARN, INFO, and ERROR) of nodes as they run.)
相關(guān)命令:
$ rosrun rqt_console rqt_console ? ? ?#效果見圖8
$ rosrun rqt_logger_level rqt_logger_level? ? ? ? ? #效果見圖9
‘rqt_logger_level->改變節(jié)點(diǎn)日志的冗長(zhǎng)級(jí)別’這句話啥意思?感覺怪怪的
解釋:實(shí)際上,運(yùn)行時(shí),如圖9最右邊日志列表所示,有以下級(jí)別:Fatal、Error、Warn、Info、Debug,級(jí)別依次降低。在運(yùn)行‘$ rosrun rqt_logger_level rqt_logger_level’這句話后,會(huì)彈出一個(gè)管理界面,你可以選擇你關(guān)注的誒之類別是那個(gè)level,比如你選擇‘warn’,辣么,在console的管理界面就只會(huì)顯示W(wǎng)arn日志以及它級(jí)別以上的日志,比如Fatal、Error,而不會(huì)顯示‘Info、Debug’這些level的信息。同理,如果只選擇Fatal,則只顯示Fatal級(jí)別的信息
10、多個(gè)節(jié)點(diǎn)同時(shí)發(fā)布-roslaunch
roslaunch可以將同一個(gè)launch file里的節(jié)點(diǎn)同時(shí)發(fā)布:$ roslaunch [package] [filename.launch]
11、ROS文檔編輯-rosed
rosed可以僅僅根據(jù)包的名字和文檔名字就編輯文檔,而不需要寫該文檔的路徑:$ rosed [package_name] [filename]
msg:ROS使用了一種簡(jiǎn)化的消息類型描述語言來描述ROS節(jié)點(diǎn)發(fā)布的數(shù)據(jù)值。通過這樣的描述語言,ROS能夠使用多種編程語言生成不同類型消息的源代碼。ROS提供了很多預(yù)定義消息類型。如果你創(chuàng)建了一種新的消息類型,那么就要把消息的類型定義放到功能包的msg/文件夾下。在該文件夾下,有用于定義各種消息的文件。這些文件都以.msg為擴(kuò)展名。消息類型必須具有兩個(gè)主要部分:字段和常量。字段定義了要在消息中傳輸?shù)臄?shù)據(jù)類型,常量用與定義字段的名稱。
ROS消息中的一種特殊數(shù)據(jù)類型是報(bào)文頭,主要用于添加時(shí)間戳、坐標(biāo)位置等。報(bào)文頭還允許對(duì)消息進(jìn)行編號(hào)。通過在報(bào)文頭內(nèi)部附加信息,可以知道是哪個(gè)節(jié)點(diǎn)發(fā)出的消息,或者可以添加一些能夠被ROS處理的其他功能。
創(chuàng)建一個(gè)消息:
$ roscd beginner_tutorials
$ mkdir msg
$ echo "int64 num" > msg/Num.msg
srv:ROS使用了一種簡(jiǎn)化的服務(wù)描述語言來描述ROS服務(wù)器。這直接借鑒了ROS msg消息的數(shù)據(jù)格式,以實(shí)現(xiàn)節(jié)點(diǎn)之間的請(qǐng)求/響應(yīng)通信。服務(wù)的描述存儲(chǔ)在功能包的srv/子目錄下.srv文件中。
創(chuàng)建一個(gè)服務(wù):
$ roscd beginner_tutorials
$ mkdir srv
#這次我們不再手動(dòng)創(chuàng)建服務(wù),而是利用roscp從其他的package中復(fù)制一個(gè)服務(wù)。
$ roscp rospy_tutorials AddTwoInts.srv srv/AddTwoInts.srv
其實(shí),因?yàn)榻sg和srv的時(shí)候,同時(shí)需要修改beginner_tutorials功能包下的package.xml和CMakeLists.txt兩個(gè)文件,這部分修改配置的內(nèi)容沒有在此顯示,有需要的請(qǐng)點(diǎn)擊ROS消息和服務(wù)-msg和srv。
好的,ROS文件系統(tǒng)架構(gòu)以及概念總結(jié)到這里,希望對(duì)大家有所幫助,再次強(qiáng)調(diào),更加準(zhǔn)確的ROS入門知識(shí)請(qǐng)直接查看官網(wǎng)ROS Tutorials。同時(shí)請(qǐng)大牛不吝賜教,非常感謝!