用 Python 撰寫自己的節點

如果要了解如何用 C++ 寫一個簡單的節點的話,可以參考這篇

為了撰寫這篇筆記,我稍微了作了一下功課,發現我手邊的資料,都是教人如何用 C++

寫節點,似乎這樣比較能施展計算的效能,以及與現在的許多主流函式庫接軌。但別忘了,ROS也支援 Python
,而隨著機器學習與深度學習的應用再者幾年來逐漸興起,如

Tensor Flow 等等用 Python



為其主要語言的函式庫也獲得愈來愈多廣泛的採用`我後來更發現,如果還想要加入 Copyleft 版權的圖形化使用者介面(GUI)的話,那
Python 中的 Tkinter 絕對是我的第一且唯一首選。GUI 方面,我會再這篇之後,另外撰寫我的使用心得,而現在,我們只討論幾項基本功。
 


為什麼要用 Python 寫節點?
 


如前所述,Python 的語法簡單,且編譯也是直截了當,又是一個 OOP的語言,很適合程式初學者上手。就我個人經驗而言,Python
有以下優點:
 

  • 儘管身為直譯式語言,速度比不上編譯式語言,如 C/C++ ,但在絕大多數情況,在沒有特別的執行速度下,Python 語法其實是勝任愉快的。 

  • 語法簡單,編譯容易,可以在短時間內打造出簡單的原型軟體(Prototype) 

  • 如前所述,Python 有許多好用的函式庫都以模組化,且都以可直接當場線上下載安裝,使用方便,這樣的資源絕對不要浪費 

  • BSD 版權的 GUI 只有 Python 有,且參考資料眾多,是我目前實作使用者介面的首選。(Qt 為 GPL,一般公司行號會選擇迴避…咦?我說漏嘴了嗎?快畫刪除線~~!) 

  • 在 ROS 中的 Python 節點編譯也超簡單,下面就會看得到。


本篇討論的架構
 

  我們會以 ROS 官方教學的版本為參考,手把手寫出一個有收發功能的節點,之後再加上參數與調整的方法,在最後,我們以實際寫一個簡單的應用收尾。



節點的主幹
 


首先,我們先寫一個 Python 程式的主要架構出來,後面再加上肌肉和內臟。在我們的 Package 路徑下,確認 CMakeLists.txt
裡面的 find_pakage (catkin REQUIRED …) 下有 rospy,再檢查 package.xml
裡,<run_depend>有加入 rospy即可。整個 CMaakeLists.txt 看起來會像這樣:
 

CmakeLists.txt 

cmake_minimum_required(VERSION 2.8.3) 

project(rosnode_tutorial) 


 
find_package(catkin REQUIRED) 


catkin_package() 

 


是的,您沒看錯,既然是直譯式的程式,當然不需要 add_executable 這項。 

package.xml 


<?xml version="1.0″?> 

<package> 


<name>rosnode_tutorial</name>
 


<version>0.1.0</version>
 

<description>A simple exercise to write python
node.</description>
 

<maintainer email="todo@todo.com">Megacephalo</maintainer> 


<license>BSD</license> 

<author>Megacephalo</author> 

<buildtool_depend>catkin</buildtool_depend> 

<run_depend>geometry_msgs</run_depend> 

<run_depend>rospy</run_depend> 

</package> 


  
開一個 scripts/ 的資料夾,在裡面,我們創一個新的檔案,就稱為 rosnode_tutorial.py 好了。 

rosnode_tutorial.py 

#! /usr/bin/env python 

from std_msgs.msg  import String 


def talker(): 

   Print(“")


def main():
 

    try: 

        talker()

    except: rospy.ROSInterruptException:
      
pass 

Main()  # Call main function 

上面的程式指架構了一個主體,目的是確保我們的架構本身並不會出錯。可以看的出來,由於每一句程式碼都沒有 C/C++ 那樣最後加上一個";" ,所以

Python 是一個在語法上對縮排相當挑剔的傢伙。我刻意在 talker() 這個函式下面,只放了一個 print (“")當作 placeholder
,有點像以前的王牌推銷員那樣,把自己的腳卡進家家戶戶的門縫裡,當對方想趕緊把門闔上的時候,就會發現根本沒辦法關起來,而這時推銷員便可以再跟可憐的住戶多推銷幾分鐘。               
 



編譯 


先學會編譯,並不是一件壞事。其實很簡單,首先改這個程式的允許存取權限: 


$ chmod a+x rosnode_tutorial.py 


這時,如果你到這個程式的路徑上,直接執行這個節點的話,如: 


$ ./rosnode_tutorial.py
 


便可以檢查是否有出錯,或執行成功。還沒結束!我們要讓 roscore 連結得到這支程式,因此還是需要 catkin_make 一次,這樣連結才會生效。 


$ catkin_make
 


然後,為了讓 roscore 確實產生連結,這邊有一個小技巧: 


$ rospack profile 


Linked up ! 好,測試一下: 


$ rosrun node_tutorial node_tutorial.py
 

執行,應該會…什麼都看不到,也沒有半點程式執行錯誤時跳出的跡象,這就表示,成功了! 


發布功能
 


好,我們現在加入了 import rospy 以及 talker() 裡面的內臟筋肉後,程式變成了一個 ROS 節點。如下:

rosnode_tutorial.py 

#! /usr/bin/env python 

Import rospy  from std_msgs.msg
import String 


def talker():

rospy.init_node
(‘talker’,
anonymous=True)
    
pub =  
rospy.Publisher(‘chatter’, String, queue_size=10)
 
rate = rospy.Rate(10) # 10hz

while not rospy.is_shutdown():
 
hello_str = “hello world %s" % rospy.get_time()

rospy.loginfo(hello_str)

pub.publish(hello_str)

rate.sleep()
 


def main()

try:
talker()

  
except   rospy.ROSInterruptException:
pass
 


main()   # Call main function
 


橘色的部分,是構成這個 Python 節點的關鍵程式碼。如果有用 C++ 寫過節點的朋友,保證對 


rospy.init_node(‘talker’, anonymous=True)
 


不陌生,顧名思義,就是初始這個節點的辦法。在沒有這行程式碼的情況下,這個節點無法與 roscore 溝通。第一個引述為這個節點的名稱,叫
“talker",一定要是其名稱,不可以包含"/"在前頭。在 ROS 中,每個節點有其獨特的名稱,因此,若有兩個同樣名稱的節點一起被啟動,則後啟動者會踢掉先發者。要避免這種狀況,可以設定成
anonymous = True,讓 rospy 幫我們位同樣的名稱的每一個節點,指定一個單一的名稱。
 


pub =
rospy.Publisher(‘chatter’, String, queue_size=10)
  


第二行也顯而易見,宣告一個 pub 物件發佈一個大小為 10 個字元的字串訊息,名稱為 “chatter"。

這個 pub 物件接著就負責將處理好的訊息,直接發不出來,在這個情況下,是字串變數 hello_str。如下:
 


pub.publish
(hello_str) 



訂閱功能
 


我們已經完成了發佈的功能,接著,我們要讓該節點去訂閱別人的訊息。回到原本的程式碼,讓我們再原本的程式碼上動點手腳:
 

rosnode_tutorial.py 

#! /usr/bin/env python 


Import rospy from std_msgs.msg
import
String 


def talker():

  
rospy.init_node(‘talker’, anonymous=True)    
  
pub = rospy.Publisher(‘chatter’, String,   queue_size=10) 
rospy.Subscriber(“chatter", String, callback)
  
rate = rospy.Rate(10) # 10hz

while not rospy.is_shutdown():

hello_str = “hello world %s" % rospy.get_time()

rospy.loginfo(hello_str)

pub.publish(hello_str)

rate.sleep()


def callback(msg):

rospy.loginfo(rospy.get_caller_id() + “I heard %s", msg.data)
 



def main()
   
try:

talker()

except 
rospy.ROSInterruptException:
pass


main()   # Call main function
 


這種寫法稍微白癡了一點,不過卻也發揮了教學效果。這次,只要注意綠色的那幾行就好。rospy 在這邊,扮演了 C++ 節點中的 NodeHandle 角色,訂閱了一個叫 “chatter" 的 Topic
,那這…這這這..不就自己發出來的訊息自己吃嗎?啊呀!別大驚小怪啊!這世界上無奇不有,就連大象的鼻子從象頭伸出來,為了喝水吃東西,又可以被再度放入象嘴中(這是什麼鬼比喻?),就連蟒蛇(Pit
hon)都可以自己咬自己的尾巴,而因此讓目睹了這個景象的德國有機化學家弗里德里希·奧古斯特·凱庫勒 (Friedrich
August Kekulé) 破解了苯的化學結構。好了,說遠了。就醬!
                                           


rospy.Subscriber(“chatter", String, callback)  

這個"訂閱"函式第一個引數,便是 Topic 的名稱,第二引述,便是該話題的資料型態,最後一個引數,是要將這個 Topic 餵到哪個涵是裡去,通常是一個
callback 函式,如果想多了解這個函式,可以參考我之前寫過的
這篇 


調整變數
 


參數化一些變數的值是寫一支好程式的好習慣,可以增加程式的維護性以及可擴充性。假設我們想讓 Topic
的名稱可以讓使用者任意調整,便不應該讓話題的名稱被寫死。我們將 chatter 這個寫死的 topic 改成一個可以任意變動的參數。我們宣告一個變數:


myTopic
 


然後讓這個變數可以被使用者更改,使用者只要將 “my_topic"這個標籤的值指定值即可,但我們先同時設了一個預設值,叫"chatter": 
 


MyTopic = rospy.get_param (“my_topic", “chatter")
 


然後,套用到我們的節點中,就成為這樣:

rosnode_tutorial.py 

#! /usr/bin/env python 


Import rospy from std_msgs.msg
import String 


def talker():

rospy.init_node
(‘talker’, anonymous=True)
    
# 參數化輸入以及輸出的 Topic

MyTopic = rospy.get_param (“my_topic", “chatter")

pub =
rospy.Publisher
(myTopic, String, queue_size=10) 
rospy.Subscriber(“chatter", String, callback)
  
rate = rospy.Rate(10) # 10hz

while not rospy.is_shutdown():
 
hello_str = “hello world %s" % rospy.get_time()
 

        rospy.loginfo(hello_str)

        pub.publish(hello_str)
rate.sleep()
 



def callback(msg):

rospy.loginfo(rospy.get_caller_id() + “I heard %s", msg.data)
 



def main()
:


try:

talker()

except 
rospy.ROSInterruptException:
pass
 


main()   # Call main function
 


更多關於如何設定、取得參數的方法,可以參考
官方教學網頁 



與 Roslaunch 結合,將變數調整變得有彈性
 


在 C++ 的節點中,也有類似 get_param 這樣的函式,而其實 C++ 以及 Python 寫成的節點,都可以直接從終端機指令中,或者
launch file 裡面作設定。在 launch file 當中,我們現在可以這樣寫,將 myTopic 設定成我們想要的名稱。
 

rosnode_tutorial.launch 

<?xml version="1.0″ ?> 

<launch>
<arg name="my_topic" default="my_chatter" />
 


<node pkg="rosnode_tutorial" type="rosnode_tutorial" name="rosnode_tutorial" >

<param name="my_topic" value="$(arg
my_topic)" />
</node>

</launch>
 

其實。launch file 裡面,可以當場設定 value="" 的值即可,但我們為了未來的可能擴充作準備,因此先用 <arg> 設定參數值,再代入
<param>的方法,讓這個 launch 檔方便未來被其他 launch 檔呼叫時,裡面的參數也方便被修改。這是一個好習慣,請讀者們務必善加利用。
 


實務應用:Teleop Twist
 


我們最後便展示一個可以用鍵盤遠端遙控機器人的節點怎麼寫好了。其中的功能很簡單,便是收到使用者按下什麼鍵,再予以發佈 twist
指令,讓機器人左右倫轉動特定角度,可以想像成我們撥動手中的搖桿,只要一直往前壓著搖桿,每一毫秒搖桿便會讓機器人往前走一小段距離。這邊不細講了,直接看原始碼。喔,順帶一提,這其實是
teleop_twist_keyboard 的程式碼,原始儲存庫在
這邊,不過其實可以直接用
Debian 安裝,所以請踴躍安裝使用。

CMakeLists.txt 

cmake_minimum_required(VERSION 2.8.3) 

project(teleop_twist_keyboard)

find_package(catkin REQUIRED)
catkin_package() 


## Mark executable scripts (Python etc.) for
installation
 


## in contrast to setup.py, you can choose the
destination
 


catkin_install_python(PROGRAMS
teleop_twist_keyboard.py 



DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}

)


Package.xml 

<?xml version="1.0″?> 

<package> 

<name>teleop_twist_keyboard</name>
<version>0.6.0</version>
 

<description>Generic keyboard teleop for twist robots.</description>

<maintainer email="namniart@gmail.com">Austin Hendrix</maintainer>

<license>BSD</license> 


<author>Graylin Trevor Jay</author>


<buildtool_depend>catkin</buildtool_depend>

<run_depend>geometry_msgs</run_depend>

<run_depend>rospy</run_depend>

</package>

teleop_twist_keyboard.py 

#!/usr/bin/env python 

import roslib; roslib.load_manifest(‘teleop_twist_keyboard’) 

import rospy 

from geometry_msgs.msg import Twist 

import sys, select, termios, tty 


msg = “"" 


Reading from the keyboard  and Publishing to
Twist!

—————————

Moving around:

u    i    o

j    k    l

m    ,    .
 


For Holonomic mode (strafing), hold down the shift
key:

—————————

U    I    O

J    K    L

M    <    >

t : up (+z)

b : down (-z)

anything else : stop

q/z : increase/decrease max speeds by 10%

w/x : increase/decrease only linear speed by 10%

e/c : increase/decrease only angular speed by 10%

CTRL-C to quit

“""

moveBindings = {

‘i’:(1,0,0,0),

‘o’:(1,0,0,-1),

‘j’:(0,0,0,1),

‘l’:(0,0,0,-1),

‘u’:(1,0,0,1),

‘,’:(-1,0,0,0),

‘.’:(-1,0,0,1),

‘m’:(-1,0,0,-1),

‘O’:(1,-1,0,0),

‘I’:(1,0,0,0),

‘J’:(0,1,0,0),

‘L’:(0,-1,0,0),

‘U’:(1,1,0,0),

‘<‘:(-1,0,0,0),

‘>’:(-1,-1,0,0),

‘M’:(-1,1,0,0),

‘t’:(0,0,1,0),

‘b’:(0,0,-1,0),

}
 


speedBindings={

‘q’:(1.1,1.1),

‘z’:(.9,.9),

‘w’:(1.1,1),

‘x’:(.9,1),

‘e’:(1,1.1),

‘c’:(1,.9),

}


def getKey():

tty.setraw(sys.stdin.fileno())

select.select([sys.stdin], [], [], 0)

key = sys.stdin.read(1)

termios.tcsetattr(sys.stdin, termios.TCSADRAIN,
settings)

return key
 
def vels(speed,turn):

return “currently:\tspeed %s\tturn %s " %
(speed,turn)
 

if __name__=="__main__":
settings = termios.tcgetattr(sys.stdin)

pub = rospy.Publisher(‘cmd_vel’, Twist, queue_size = 1)
rospy.init_node(‘teleop_twist_keyboard’)

speed = rospy.get_param(“~speed", 0.5)

turn = rospy.get_param(“~turn", 1.0)

x = 0

y = 0

z = 0

th = 0

status = 0


try:

print msg
 
print vels(speed,turn)
 


while(1):
 
key = getKey()
 
if key in moveBindings.keys():
 
x = moveBindings[key][0]
 
y = moveBindings[key][1]
 
z = moveBindings[key][2]
 
th = moveBindings[key][3]
 
elif key in speedBindings.keys():

speed = speed * speedBindings[key][0]

turn = turn * speedBindings[key][1]

    print vels(speed,turn)
if (status == 14):

print msg
 

     status = (status + 1) % 15 
else:

x = 0
 
y = 0
 
z = 0

     th = 0 


if (key == ‘\x03’):

break
 

      

    twist = Twist() 

    twist.linear.x = x*speed; twist.linear.y = y*speed;
twist.linear.z = z*speed;
 


twist.angular.x = 0; twist.angular.y = 0;
twist.angular.z = th*turn
 


pub.publish(twist)
 

    except: 

        print e 


finally:
 

    twist = Twist() 

    twist.linear.x = 0; twist.linear.y = 0;
twist.linear.z = 0
 
twist.angular.x = 0; twist.angular.y = 0;
twist.angular.z = 0
 


pub.publish(twist)

termios.tcsetattr(sys.stdin, termios.TCSADRAIN, settings)

 

廣告

如何讓一台機台中的 Launch 檔也能啟動其他機台中的節點?

distributed-computing
之前看了林信男的這篇如何用一個 launch 檔啟動期胎台機器人上的節點(程式),看得我也心癢癢的,想說這樣的功能,真是 ROS 界的福音啊!趁著研究告一段落,比較有空的時候,也來試試。以下就是我的使用心得!
在開始之前,請先確定你已經完成了 DSA 無密碼遠端連線的設定,請參考這裡。如果還沒設定或還沒閱讀過,請連過去看。對!就是現在!我在這邊等著(啜飲焦糖瑪奇朵中)。
OK了嗎?好,確定一下你的 ~/.bashrc 裡面已經設定好 ROS Master 地址、你自己的 workspace 位置。都設定好了嗎?那我們繼續。
Launch 檔中有幾款標籤可以自由使用,請參考 這篇官方Launch/XML machine 標籤的用法教學 。雖然裡面有提供 password 選項,但既然我們能不須密碼遠端登入,那洩漏密碼這件事遍布成問題了。
ROS 的 Launch 檔裡,允許使用者針對各機台上的節點做啟動,但不可以遠端啟動另外一個 Launch 檔。此外,當初的設計應該是讓 Master 端用這樣的「至尊 Launch 檔」呼風喚雨,所以如果你是在非 master 的機台上呼叫這樣的 Launch 檔,你只會開啟這台基台上的節點而已。這是使用尚要注意的地方。在撰寫這類至尊 Launch 檔的語法上,我們需要用 標籤先宣告各機台,然後啟動各節點時,用 裡面的 machine="" 來指定機台。
以下是一個範例檔。有很多標籤,既然是 Optional ,我就不使用了:
 ———————————————————————-
  address="myRobot.local"
  user="bot" />
  address="$(arg client_ip)"
  user="$(arg client_name)" />

——————————————————————

自己使用的心得

雖然期盼已久的遠端單 launch file 開啟節點的夢終於實現了,但是我也碰到另外兩個問題,

問題一

所有的文件都解釋了如何啟動遠端節點的實作方法,但是竟然沒有超出四篇在談論如何遠端啟動對方的 launch 檔,亦言之,無法用 machine 標籤將別台機器的 launch 檔包進來。對我而言,目前我手上的專案根本無法一個節點一個節點置入 machine 標籤,因為一個專案就包括了數十個節點,改完手會斷。因次,我個人的使用經驗是挫折的,目前好像尚未能找到這樣的實作方法,看起來又必須重新回覆到之前遠端到各機台並個別啟動該機的 launch file 模式了,否則根本無法順利運作。

問題二

若你在非 master 節點所在的機台上啟動這個可控遠端的 launch 檔,你會遭遇到一則錯誤的訊息,就是 ROS 找不到 master, 所以無法啟動節點,laumch 就此關閉。這就表示,你只能在 master 的機台端啟動該 laumch 檔。
如果你的 master 剛好就在你現在所使用的電腦上,那就沒問題了,但如果你跟我一樣,master 放在機器人端,那麼你依舊每次還要遠端過去,然後才執行該 launch 檔,用久了自己都會嫌麻煩。那你可能會問,那為什麼不乾脆直接把 master 設在自己的電腦上就好?Well, 這世界上永遠都有特例,例如,當你所使用的機器人是公用的,隨時都會有好幾個人一起連到機器人的電腦上。除非今天你是老闆,否則應該沒有人敢一直請你開電腦,然後才遠端到你的電腦上,只為了啟動他的程式吧?
所以,主要的問題是 master 節點,這也可能是為什麼 ROS 2.0 可以改進的,就是去除必須啟動 master 節點才能做事的奇怪要求。
相關主題文章:
更多精采文章,請回目錄瀏覽!

每次登入都要輸入密碼?用 DSA 實作無密碼遠端登入!

由於最近必須把所有的研究成果整合到一台全新的機器人平台上,所以有機會來嘗試一些之前沒時間嘗試的工具。譬如說只用一個 launch 檔同時開啟多台機器上的各個節點,這樣勢必會讓現在啟動機器人的方法發生革命性的變化,至少應該會更簡單。但在這之前,我想分享一下怎麼設定不需要密碼登入的遠端連線這回事,有這個前置動作,才會有更好的連線控制方法。好,那我們來實作看看!

Step 1  至少先確認能遠端

首先,我們需要確認兩台電腦能彼此遠端。請參考我的另一篇文章
在這邊只提醒各位,機器人端和客戶端個別都需要安裝 openssh-client 和 openssh-robot
$ sudo apt-get install openssh-client
$ sudo apt-get install opensh- server
直白來說,前者是遠端到別人那端時使用的,後者則是讓自己當伺服器或接受別人連到我們這邊。
如果不確定自己有什麼裝了什麼沒裝,可以安裝並使用 aptitude 這個小工具幫忙搜尋(如果你的系統中沒有。直接 apt- get install 它),用 Aptitude 搜尋方法如下:
$ aptitude search openssh*
在這一步快進入尾聲前,請確認自己的 .bashrc 內已經有以下:
export ROS-HOSTNAME=你的 Zeroconf 名稱
export ROS_MASTER_URI=http://[Master 的 Zeroconf 名稱]:11311/
例如我的設定如下:
export ROS_HOSTNAME=charly-MSI.local
export ROS_MASTER_URI=http://beebot.local:11311/
只要輸出的所有程式那行的前面出現 “i", 那麼就代表該程式已經安裝。

Step 2 打造金鑰

在機器人的終端機上打:
$ ssh -keygen -t dsa
這時終端機應該會跳出類似以下的訊息:
Enter file in which to save the key (/home/[機器人 host]/.ssh/id_dsa)
它已經有預設的儲存位置了, 就給把公鑰直接儲存在該路徑上吧!我們之後會需要它, 所以這一步就給它大方 Enter 鍵揍下去(噹噹噹噹!)
終端機會在輸出一行訊息:Enter passphrase:
就輸入密碼!
Enter same passphrase again: 再輸入密碼 Orz
所以目前公鑰存在以下路徑:/home/[我的機器人]/.ssh/id_rsa.pub
還有自己的私鑰, 這個永遠別給別人, 記得喔! /home/[我的機器人]/.ssh/id_rsa

Step 3 給對方公用金鑰

是的。你的家要讓朋友隨時進出,那你就要給朋友你的鑰匙。但這份鑰匙為了門禁驗證用,你只把半個鑰匙給人家,自己保留另外一半,或者用另外一種方式看,有點像你自己這邊設置門鎖。若其他朋友冒充你的朋友拿不知哪來的一半鑰匙開門,那對不起,依舊無法打開你家的門。
所以,再電腦遠端驗證中,你自己持有一把私鑰,給想要連近來的電腦一把公鑰。那要怎麼給呢?首先,先改公鑰(.ssh)執行權限:
$ cd
$ chmod 755 .ssh
複製公鑰到要遠端連進來的電腦上:
$ scp ~/.ssh/id_rsa.pub [客戶端電腦]@[客戶端電腦的 IP 或 Zeroconf]: .ssh/authorized_key
例如:
$ scp ~/.ssh/id_rsa.pub charly@charly-MSI:.ssh/authorized_key
現在,遠端到你的客戶端電腦上,打開終端機後,設定公鑰權限:
$ chmod 600 ~/ssh/authorized_keys
好了!設定完成!

Step 4 最後一次需要密碼的登入,此後一勞永逸

假設你從你的客戶端電腦用 ssh 遠端連線到機器人主機,例如:
$ ssh bot@myRobot.local
系統會問你最後一次輸入對方的密碼,一旦輸入好並登入後,之後便在也不會要求你輸入密碼。你已經可以順利以不輸入密碼的方式,登入對方的電腦。同樣的,若對方要遠端連線登入到你這台電腦,也必須照上述設定步驟,只是這次轉換角色而已。

Step 5 (Optional) 寫一個批次檔讓你每次都能輕鬆登入

科技始於人性。我不想每次都一直打 ssh 指令,有沒有更快的方式,讓登入便得更便捷自動?有的!批次檔現在可以更安全的幫你再不洩漏密碼的強況下,自動遠端登入。先在你中意的路徑下,建立一個文件檔,隨便取什麼名字,副檔名為 .sh,裡面打下遠端登入的指令即可。以下範例是我的遠端批次檔:
#! /bin/sh
ssh bot@myRobot.local
就這麼簡單!
相關主題文章:
 更多精采文章,請回目錄瀏覽!

最簡單讓你的平板變成電腦延伸螢幕的方法

(聲明:如欲轉載本文章,或者節錄文中的圖片或文字,請記得寫上出處。謝謝!)

自從辦公桌上架了第二顆螢幕後,就再也回不去使用單螢幕的時代了,理由很簡單,有個延伸桌面,真的可以把要同時進行的作業同時攤開來方便檢視,有使用延伸螢幕的人絕對知道我在說什麼。尤其時值研究開發時期,又要蒐集資料,撰寫論文的時候,更是拖不開使用雙螢幕。我之前想到使用家裡的電視當第二顆螢幕,但是占著不給爸媽看電視,好像也很不肖欸?

把電視當延伸螢幕
買一條 HDMI 線,一端接上電腦,另外一端接到電視,這樣就可以把電視當延伸螢幕了。但是除非你獨居,或電視本來就是你自己的,要不然有時並不是最好的辦法

很可惜最近都直接拿著筆電離開辦公室工作,但還是想要雙螢幕,怎麼辦?也沒有一萬多塊閒錢可以添購平板可攜式螢幕,但是手邊剛好有一台平板,且平板攜帶上比帶另一顆螢幕簡單多了。所以我腦筋就動到這台平板上。

要把平板變成延伸螢幕並不是這麼簡單。在不考慮直接買螢幕接上筆電,又要盡量省錢的前提下,我找到兩種解決方法,而且都有親身試驗過!

方法一:不管你是使用哪一種作業系統,讓專業的來就對了!

實際上就是直接上 Google Play 或 iStore 買人家開發好的 App,在平板端裝上 App,然後再電腦端安裝相對應的接口,然後透過 Wifi,或者USB連接電腦與平板,把平板的「開發人員選項」打開來(在 Adnroid 4.2 版之後,啟動的方法很像在找彩蛋,可以參考這裡),Voila !! 你就可以把平板當成延伸螢幕來用!

每款應用軟體都有各自的優缺點,所以在付費使用之前(是的!沒有一款是免費的!我在想可能開發真的很費工,如果發不出薪水,員工可能會告上法院!),請謹慎評估,符合自己需求的,才是最適合您的軟體。另一方面,有網友也指出,使用 Wifi為連接媒介的軟體會受限於網路連接的頻寬以及速度,所以在流暢度,或者在跨螢幕視窗的同步上,絕對無法達到最佳化,但至少這類軟體避免掉裝置通訊埠之間繁雜的設定,只要在同一個子網路下找得到對方,就絕對可以確保連得上。反之,走 USB 線的軟體的優點,就是可以在周遭環境沒有或找不到 Wifi的情況下,照樣可以順利連線,並且可以確保使用上的流暢度,包括跨螢幕視窗運作的流暢度,真的遠遠超越 Wifi 連接的軟體(看一下下面的影片就知道了!)。那為什麼還有人想使用前者?其實走 USB 線的軟體也有它的罩門(這就是為什麼我先暫時放棄的原因),在使用上,若兩個裝置打從出娘胎以來,就「合不來」,那你在怎麼努力修改設定,仍然不會讓他倆「相見歡」,原因我寫在下面的章節。

關於有哪些可以用的軟體,既然有網友寫了,這邊便不再多作贅述,直接看這邊吧!感謝!真的寫得很詳盡!下面展示一下 TwomonUSB 的 Demo 影片,就可以知道我在講什麼了!

讓我來講一下我的親身體驗吧!我也是查了幾小時的資料,甚至為此將我郵局的金融卡功能打開(就上郵局跟他講把所有卡的國外交易功能什麼的,全部功能都打開!),方便我在 Google Play上購買軟體。

看來看去,我決定使用走 USB 線的App,先嘗試安裝免費版本的 Splashtop Wired Display ,在短短的十分鐘內看看能不能美夢成真。安裝了電腦端軟體後,也下載並安裝 App 後,我把平板電腦的開發人員選項啟動,勾選了USB偵錯選項。電腦有偵測到平板裝置,但是就是不知道為什麼無法讓電腦端跟平板端的程式連線。妙的是用同一家公司開發的遠端軟體就連得上去。幾個小時候的嘗試後,我放棄。

Tablet as second monitor
source: http://mashable.com/2012/11/01/tablet-second-monitor/#1uql0LW91EqU

接著,雖然掛念之後要在 Linux 系統下無雙螢幕,Windows卻能享受的殘念下(因為我的筆電是雙系統的),我便購買了 TwmonUSB 這款頗受好評的 App。TwomonUSB 是由一家韓國公司 DevGuru 開發的,致力於讓平板變成電腦的延伸螢幕,而且比其他同款軟體好的地方,是它已經幫你安裝好所有需要的套件,所以你其實不需要親自設定什麼就可以用了,嗯…據說。

我忍痛的自掏腰包購買了 TwomonUSB,並設定好了後,奇怪?還是無法使用。莫非,我的平板就是跟我的筆電「合不來」?花了半個小時冒冷汗爬官網上的文,試過所有方法後,還是無法讓程式跑起來!購買後兩小時內,心灰意冷的退費,萬念俱灰又不甘心的放棄了。不過從安裝這個軟體的過程中,我也逐漸聊解這種軟體是怎麼運作的。這也就是我採用方法二的原因之一。

方法二:窮人超瞎玩法

DSC05471
將平板變成電腦的延伸螢幕

就像上面章節講到的,比起在 Windows上使用,我更想要應用在 Linux 系統下。Splashtop 在 Linux 上有開發 beta 版的 Splashtop Streamer,這只是連線的接口,真正發揮功能的,是智慧裝置端的 App,讓遠端桌面或者延伸螢幕的軟體可以連上電腦。

在繼續進展之前,來大致上講述一下連接的原理。要怎麼讓兩台電腦互相協作,並不是像拿一台螢幕接上電腦這麼簡單。兩台電腦其實很像是兩個自尊心很強的 Hosts,沒有人服氣令一個人。所以延伸螢幕軟體必須像是在電腦端宣告有一顆螢幕已經接上電腦,這包括安裝模擬用的螢幕顯卡程式,螢幕使用的 VGA接埠程式、也許還有VGA轉成USB訊號的程式。同時在平板電腦端則要設法讓平板變成一個從遠端桌面形式轉換後變成的延伸螢幕軟體。換句話說,延伸螢幕其實就是結合 VNC、遠端桌面、遠端輸入等等程式組成的軟體,並不實這麼簡單的和事佬,難怪人家寫好都要收費!

但我也找到了另外一種方法,是在英文論壇中找到的,不得不說這個老外還滿厲害的,不愧是 Taiwan Number One! Taiwan Number One !我草泥馬!!LOLOLOL

其實方法很簡單,就是在電腦端創建一個虛擬的第二顆螢幕,然後再用遠端軟體直接顯示這個虛擬螢幕,大功告成,請好好享用!

所以這邊問題就要分解成兩個步驟,第一,如何創造一個虛擬的第二螢幕?第二,使用遠端桌面。

Step 1 使用 RandR 創立虛擬顯示器(螢幕)

第一個問題的解法,我使用 RandR 這個管理 Linux 各顯示器埠口的工具。首先,打開終端機,安裝 xrandr,這樣打

$ sudo apt-get install arandr lxrandr

安裝好後,執行 RandR 來看看目前偵測得到的顯示器埠口。打開終端機,打:

$ xrandr

電腦應該會回覆:

Screen 0: minimum 8 x 8, current 2944 x 1080, maximum 16384 x 16384
eDP1 connected 1920×1080+1024+0 (normal left inverted right x axis y axis) 344mm x 194mm
1920×1080      60.1*+   59.9
1680×1050      60.0     59.9
1600×1024      60.2
1400×1050      60.0
1280×1024      60.0
1440×900       59.9
1280×960       60.0
1360×768       59.8     60.0
1152×864       60.0
1024×768       60.0
800×600        60.3     56.2
640×480        59.9
VGA1 disconnected (normal left inverted right x axis y axis)
DP1 disconnected (normal left inverted right x axis y axis)
HDMI1 disconnected (normal left inverted right x axis y axis)
HDMI2 disconnected (normal left inverted right x axis y axis)

拿我筆電作範例。從回傳的訊息中,可以看得出有五個顯示裝置:eDP1, VGA1, DP1, HDMI1, 和 HDMI2。其中 eDP1 為這台電腦的主要顯示器,它有好幾個解析度,以及各解析度的更新率(單位:Hz)。打星號(*)的,就是目前使用的解析度和更新率。

好!接下來,我們來創建一個虛擬螢幕,並把它擺在本機螢幕的左邊,請在終端機中打:

$ xrandr –addmode VIRTUAL1 1024×768

$ xrandr –output VIRTUAL1 –left-of eDP1

這樣子,我們先創立了叫做 VIRTUAL1 的虛擬顯示裝置,它的解析度為 1024 x 768,並且我們把 VIRTUAL1  的輸出放在 eDP1 的左邊。不知道為什麼,我第二行指令必須輸入個兩次才能讓顯示設定乖乖聽話。

如果再輸入指令 xrandr,現在會看到整個訊息的下方,會出現

VIRTUAL1 connected 1024×768+0+0 (normal left inverted right x axis y axis) 0mm x 0mm 1024×768         60.0*

等訊息,這樣一切正常。另外一個檢查的方式,是同時按住鍵盤上的 Windwos 及 s 鍵,透過 GNOME 的縮圖,可以看到有沒有出現第二顆螢幕。如果本機的螢幕像素反而降低,去 System Setting –> Display 裡面調回原本的最高解析度即可。從這邊,也可以看到確實有第二個顯示器。

值得注意的一件事,上述的設定在下一次開機時就會失效,網路上還有其他 xrandr 的使用方法,我的解法,是如果每次要用的時候,直接啟動 bash 文件幫我省下打那麼多指令。你要做的事,就是在你喜歡的路徑上,除存一份命名為 “virtual_monitor.sh" 的批次檔,譬如我直接存在桌面上。文件裡面這樣打(或直接這邊複製貼上):

#! /bin/bash

clear
echo “We will activate XrandR to activate virutal monitor"
xrandr –addmode VIRTUAL1 1024×768
xrandr –output VIRTUAL1 –left-of eDP1
xrandr –output VIRTUAL1 –left-of eDP1
echo “Virtual screen at your left side is activated! Enjoy!"

寫好後,儲存,關閉文件。接著,再打開終端機,cd 到你儲存該文件的路徑上,改變這份文件的可執行權限:

$ chmod a+x virtual_monitor.sh

下次要使用的時候,同樣在終端機中 cd 到這份文件的路徑上,執行:

$ ./virtual_monitor.sh

這樣應該就可以把第二顆螢幕架起來了。

如果對於 xrandr 使用上還有任何問題,可以 google 一下,譬如說這個備載齊全的網頁,或者直接在終端機打:

$ xrandr –help

或者

$ man xrandr

都會有額外的說明。

還活著嗎?最難的部份已經過了!我們進入下一步!

Step 2  使用 TeamViewer 顯示虛擬螢幕

使用了 Splashtop HD Extender 這款免費試用 App,發現提供的功能根本無法切換螢幕,爛!所以還是使用老牌且知名的遠端桌面軟體 TeamViewer。欸?那其實我也可以用另外一台電腦顯示延伸的桌面囉?沒錯!這樣就有點像是使用了 VNC 的意思了!我甚至使用我的手機當延伸螢幕!但是,這樣作有什麼意義?

廢話不多說,上 Google Play 安裝 TeamViewer 遠端控制版本。這不用我教了吧?

接著,遠端連線!我不知道為什麼我不能使用自己的 TeamViewer 帳號直接連線,那就用 TeamID 來連筆電吧!

切換顯示的螢幕。由於我的筆電使用 nVidia 顯卡,所以截至目前為止尚未支援 RandR,會產生TeamViewer 無法顯示第二螢幕的問題。nVidia 自己有開發一個類似的軟體 TwinView,可能會導致顯示上的問題。不管這麼多了!平板轉到虛擬螢幕上到一半,TeamViewer 當掉,那就用手機連看看…OK! 那再用平板連看看,兩次過後,可以顯示第二螢幕了!Yeah ! Gotcha bitch !搞定!

記得在平板端的 TeamViewer 設定中,勾選「顯示遠端游標」。

請勾選「顯示遠端游標」

至此大功告成!恭喜!你已經將你的平板轉成第二顆螢幕了,

結論

讓我們看看為了達成這項功能的花費:

平板的支架:NT$ 70

MicroUSB 訊號線:NT$ 30

姑且不算購入平板電腦的花費,總花費:NT$ 100 !! 架設所需時間,嗯…哥都替你耗費掉了,如果一切順利,你實際只需要 10 分鐘內搞定!

但是,這種方式你必須要接受以下幾件事實:

  • 跨螢幕視窗執行的流暢度?算了吧!
  • 附近沒有夠快的 Wifi AP?請自求多福!
  • 在延伸螢幕上播放影片絕對無法順暢,也就是說,只要有任何視頻,絕對無法順暢執行,甚至會拖慢其他 GUI 的顯示效果
  • 用一陣子後,或者只要連線一不穩,延神螢幕就會斷線,也就是說,程式會跳出,或者卡住當機
  • 所以最好是別在延伸螢幕上做太吃顯示資源的事。但我們既然是用來辦公的,那就乖乖用自己的文件或瀏覽靜態的網頁就好,你說對不對?

這是目前應急用的,倘若之後真的成功安裝好某個程式,或者用一組程式達到更穩定的平板轉延伸螢幕的話,再跟大家分享。同樣的,如果你有找到更好的辦法,也請不吝分享!謝謝!

好!那就先這樣吧!我打字手有點酸,時間也有點晚了!大家晚安!

 

 

 

 

更加認識 Gazebo

這篇文章實際上參考了Gazebo的官方教學,不過之後我會講解自己的實作過程。

首先,讓我們來了解組成 Gazebo 模擬的幾個中大關鍵要素。

世界檔!

這類文件主要由 Gazebo server 開啟,這類文件的格式被稱為 SDF
(Simulation Description Format),其副檔名為 .world。Gazebo已經內附了許多已經完成的世界模型,都放置在這個路徑下:<install_path>/share/gazebo-<version>/worlds.

模型檔!

顧名思義,就是描述機器人模型或者任何要放置在世界當中的文件。這類文件通常會被
<model> … </model> 的標籤包覆著。如果你想把你的模型加進一個世界檔中的話,你可以在世界檔中加加上:

 <include>
<uri>model://model_file_name</uri>
</include>
其實Gazebo已經有很多建立好的模型,你可以在官方位於 Bitbucket上的檔案庫內找到所需要的模型,執行的時候就會執行時間(Runtime)內載入,可以說是相當方便。如果你熟悉另外一種版本控制軟體 Mercurial
的話,你可以把整個模型資料庫克隆到你的本地端來:

$ hg clone https://bitbucket.org/osrf/gazebo_models

喔!別忘了先安裝 Hg (Mercurial)。
官方的教學網站都以實作 SDF格式為主,包括更進階的如何將自己的模型加入meshes、加上顏色、加上物理特性、貢獻到公共遠端檔案庫作分享,不過我將不會再多加解釋如何撰寫 SDF 文件,因為我使用另外一種方式匯入模型,想知道我怎麼做的,請看這邊

插件!(Plugins)

插件,就像在瀏覽器加了某個小軟體,就可以擋掉 Youtube
的討厭的廣告,或者提供更多方便的功能一樣,在模擬界,插件也能賦予模型或者世界更多采多姿的可能性,甚至改變 Gazebo
顯示物件的方法(據說)。插件可以直接用終端機以指令召喚,或者寫在世界檔內默默召喚。插件通常會被server啟動,但有時候 Client
也可以啟動,方便使用者即時做調整。
 
其他更多資訊,請看官方網站的介紹
 

相關主題文章:

更多精采文章,請回目錄瀏覽!

ROS 遠端連線

其實機器人本身就是一台電腦,不管你今天是用什麼主機板或開發版,到最後,一定得再接上網路,才可能跑 ROS (除非你把機器人有連上網卡的主機設成熱點,不過這樣好像治標不治本),否則會顯示「找不到 master」等錯誤訊息。其實,我們常常也會碰到需要遠端監控或操作的狀況,除了看起來比較酷以外,還有更實際的原因:我們需要將比較需要做運算的演算法,在另外一台電腦上執行,而機器人上的主機,只需要收感測器資料加控制馬達就可以了。ROS便提供了多台主機共享
Topics 的方法,藉由乙太網路存取資源,實際上多台電腦用起來,跟用一台電腦差不多,但省去許多要熟悉 Socket架設之類的麻煩。好,不囉嗦,步驟如下:

內容一覽:

1         準備步驟

1.1        自我連線檢測

1.2        雙方連線檢測

2         遠端連線

3         ROS 資源共享

1. 準備步驟
1.1 自我連線檢測

我們實際的例子,就是一台電腦連機器人:

Fig. 1.

遠端連線機器人示意圖

首先,必須先確認 Robot 端主機和 Client 端主機皆連線到同一個乙太網內。我們打開機器人電腦上的終端機,用ping 做連線檢測。這邊有兩種方式:
(1)  
IP 來檢測。如果不知道自己的IP的話,在終端機輸入:

$ ifconfig

終端機應該會輸出以下訊息:

請看 wlan0中 inet addr IP位址,這就是這台電腦的 IP 位址。看你是用什麼方式連線,如果網路是直接接在數據機上的話,應該是看 io 那部分找對應的 IP。這樣的位址會隨著你連線到不同的路由器或子網路而變更,因此如果今天要是由其他裝置遠端
ping 這台機器的話,必須先在這端知道自己的 IP。不過好處是,你將會很確定自己的位址只是對,因此連不上去可能是另外一台的網路設定出問題。

那麼現在就可以來 ping 自己。假設我取得了我的 IP,是192.168.120.101,現在來試試看:

$ ping 192.168.2.109

順利的話,終端機會出現以下訊息,

PING 192.168.2.109 (192.168.2.109) 56(84) bytes of data.
64 bytes from 192.168.2.109: icmp_seq=1 ttl=64 time=0.045 ms
64 bytes from 192.168.2.109: icmp_seq=2 ttl=64 time=0.046 ms
64 bytes from 192.168.2.109: icmp_seq=3 ttl=64 time=0.046 ms
64 bytes from 192.168.2.109: icmp_seq=4 ttl=64 time=0.042 ms
^C
— 192.168.2.109 ping statistics —
4 packets transmitted, 4 received, 0% packet loss, time 2997ms
rtt min/avg/max/mdev = 0.042/0.044/0.046/0.008 ms

表示自我連線測試成功。如果沒有,請確認實體連線是否正常,然後再檢測 Linux上網路連線設定是否正確。可以參考「埃羅魯巴特」中的疑難排解。
(2)  
使用 Zeroconf 的方式 ping 自己。Zeroconf 是一系列能自動整合網路連線的技術。你可以直接使用 Zeroconf 的名稱來取代 IP,因此就算你有多台機器都同時連線在另外一個網域上,在不清楚每台的IP情況下,仍然可以透過 Zeroconf 找到對方。Zeroconf
的名稱,就是:

[hostname的名稱].local
直接在終端機上打:

$ hostname

回覆的訊息,就是你這台主機的 hostname,譬如我的是 charly-MSI,那麼zeroconf就是 charly-MSI.local,如下:

charly-MSI

Ping 自己:

$ ping charly-MSI.local

回覆的訊息跟方法 (1) 中一樣,連線正常。

PING charly-MSI (127.0.1.1) 56(84) bytes of data.
64 bytes from charly-MSI (127.0.1.1): icmp_seq=1 ttl=64 time=0.012 ms
64 bytes from charly-MSI (127.0.1.1): icmp_seq=2 ttl=64 time=0.045 ms
64 bytes from charly-MSI (127.0.1.1): icmp_seq=3 ttl=64 time=0.046 ms
64 bytes from charly-MSI (127.0.1.1): icmp_seq=4 ttl=64 time=0.047 ms
^C
— charly-MSI ping statistics —
4 packets transmitted, 4 received, 0% packet loss, time 2999ms
rtt min/avg/max/mdev = 0.012/0.037/0.047/0.015 ms

 1.2. 雙方連線檢測

我們再次使用 ping 來互測對方連線,如果從 Client 端能連線到 Robot 端,並且反之亦然,表示連線正常。那麼我們就可以進入到下一個步驟。

Client 端終端機輸入:

$ ping myRobot.local

接著在 Robot端終端機輸入:

$ ping myClient.local

都能連上,跳到下一步。

2. 遠端連線

我們可以使用 ssh從 Client 端連線到 Robot 端:

$ ssh myRobot.local

如果你機器人的 ssh 要求比較多的話,那就連登入的使用者名稱都寫下去:

$ ssh myRobot@myRobot.local

那如果你還想要遠端連線時遠端存取圖形化使用者介面(GUI),那記得把 Xorg 打開,如下:

$ ssh –X myRobot.local

連線得到的話,輸入被遠端連線的電腦密碼,登入。

3. ROS資源共享

為了讓每台主機上的 ROS 都能共用資源,我們必須確認 Client 能知道誰是 Master,因此,我們可以打開用起來最順手的文件編輯器,譬如說我打開 vim,將以下指令存入 ~/.bashrc

$ vim ~/.bashrc

譬如說我的機器人 hostname叫 myRobot,那我們則拉到文件最後一行,在下面寫:

export ROS_HOSTNAME=myRobot.local

Client 端則也寫上

export ROS_HOSTNAME=myClient.local

那現在要讓大家知道誰是老大。如果你像我們的例子一樣,一個電腦連一個接器人的話,通常機器人會被設為 Master,電腦則為 Client,那麼就在 Client 端的 ~/.bashrc中,加入:

export ROS_MASTER_URI=http://myRobot.local:11311

這樣 Client 就知道機器人是老大。記得後面的 :11311 要加上去喔!其實你也可以將
Master 設在 Client 端,但是不管怎麼樣,永遠只能有一個 Master!這很重要,所以請容許我強調三次:

永遠只能有一個 Master

永遠只能有一個 Master

永遠只能有一個 Master

那你可能會問,那萬一有時候我想要在一台機器測完某個功能後,再連上
Master 怎麼辦?很簡單,涼拌!開玩笑的!你可以回到
~/.bashrc
中,把 export ROS_MASTER_URI那行給註解掉,儲存離開,關掉你現在在使用的終端機以及裡面的所有分頁,然後再打開新的終端機,啟動
roscore,這樣子,你就可以將這台電腦與 master
的主機徹底切割!(可謂又是另一種別開生面的神切割啊啊啊啊啊!)

接著,為了讓兩台以上的電腦同步,請記得使用
chrony
來同步時間,如果沒有這個軟體的話,在終端機中這樣安裝:

$ sudo apt-get install chrony

安裝完後,再安裝 ntpdate,一切就緒後,在 Client端終端機打:

$ ntpdate myRobot.local

如果一切正確,電腦會顯示兩者電腦的時間差,並會自動同步。

相關主題文章:

更多精采文章,請回目錄瀏覽!

站在巨人的肩膀上,下載並使用大師的作品完成自己的拼圖

在「ROS 略談基本安裝步驟」中,我們有談過可以下載不同的包裹模組化的安裝進自己的專案中那要怎麼做呢?以下會詳加解釋:


內容一覽:

1.如何安裝別人的包裹
1.1
Debian 安裝
1.2
從原始碼編譯 (build from source)
2.
使用的方法
3.
下載使用的建議
4.
更新包裹

1. 如何安裝別人的包裹

當我們開始上 Google 搜尋的時候,我們通常會看到
ROS
所提供的包裹,如果你進入該頁面,在標題的下方就會出現 ROS
的不同版本,選擇你所使用版本。往下看,會有 git source
並附有檔案庫連結,有時會註明是哪一個分支。如果進入內文閱覽,可能還能查到要怎麼直接 apt-get install
安裝以及從原始碼編譯。但上述狀況並不是每一個包裹的 ROS Wiki 頁面都有,那要怎麼安裝?

1.1 Debian 安裝

較少包裹會提供 Debian 檔,相當於 Windows
setup 安裝檔。通常只有態度嚴謹的專案會附一個交代清楚的
README
交代怎麼安裝怎麼用。在 Linux中,通常有兩種安裝方式,
(1)
下載到你指定的資料夾內,用 One software Center 將檔案安裝
(2)
使用終端機安裝。打開終端機,輸入:

$ sudo apt-get install ros-[你的ROS 版本]-[包裹名稱]

輸入密碼,按下 y ,一路綠燈,輕鬆可用。但是萬一 ROS
Wiki
上面只提供 git source 連結呢?

1.2 從原始碼編譯 (build from source)

你有兩個選擇,如果這個專案只有一個 master 分支,並且也確定這個包裹可以在你的
ROS
版本執行後,先複製git source 的網址,直接在終端機上打:

$ git clone [git source 網址]

e.g. git clone https://github.com/cra-ros-pkg/robot_localization

有時你可能只想要特定分支的檔案庫那就這樣打:

$ git clone [git source 網址] –branch [分支]

e.g. git clone https://github.com/cra-ros-pkg/robot_localization –branch indigo-devel

這樣就可以下載到你的 ROS workspace/src內。
別急,這個時候再回到上一層,到你的 workspace (workspace 最頂層的路徑),然後 catkin_make 編譯。如果沒出現錯誤的話,輕鬆可用!如果出現錯誤的話,請確認有把所需要的 dependencies 都安裝起來,可以在 終端機上打:

$ rosdep update

註:rosdep 必須在ROS安裝後,先
sudo rosdep init 初始化後,方能使用其他指令。
如果還是不行,打:

$ rosdep install [你的包裹]

然後,如果還是不行,請確認所需包裹套件等等,皆有被安裝起來,大致上就會解決問題。

2. 使用的方法

ok。下載完編譯過後,然後呢?通常 Readme 有寫好的專案都會告訴使用者怎麼用,譬如說跑 demo, 裡面各節點的輸出輸入Topics, 有哪些 rosservices,有哪些參數可以調。但若不巧什麼都沒寫怎麼辦?通常在一份 ROS 專案內,至少會有 src, devel, launch 這幾個資料夾。我的做法是直接進 launch 資料夾,打開其中一個 launch 檔。這份
launch
檔可能會啟動其他 launch files。因此只要逐步觀察,就可以發現有哪些節點或哪些 launch 檔被使用,他們之間的關係又是如何。再來,跳出 launch 資料夾,來到 src
資料夾,我的習慣是看過除了CMakelists.txt, src資料夾和 Makefile 檔後,大致了解整個專案原始碼放哪邊,所需要的標頭當和實作檔放在哪邊,nodelets 所需要的 plugin.xml 等又放在哪邊。接著就可以進入CMakelists 中大致瀏覽一下,看採用了哪些 dependencies和連結了哪些 includes。再往下移動,在 add_executable()  裡面,所謂的節點,是由那幾個 cpp 檔組成,又有幾個節點被編譯連結。 這一步做到後,就可以接續看各節點所對應的程式碼,並了解怎麼實作的。

啊!對!忘了講拿到包裹怎麼樣,當然是實際執行看看囉!了解各 launch 檔的功用後,就是要實際執行,看看有沒有像預期般執行功能。如果有,那就可以自己寫一個 launch 檔,納入某些功能,加入自己的專案中。如果到達這一步,恭喜你!你已經開始會使用這個包裹了!至於有沒有了解底下的原理,那又是另外一回事。

3. 下載使用的建議

從我自己開發中遭遇的慘痛經驗,建議讀者們如果要加入第三方包裹的功能進自己的專案內,請務必確認第三方的包裹是放在ROS工作空間可以獨立進行 git 更新的位置。換句話說,這個包裹建議不要放在讀者自己的包裹內,因為這樣,下載下來的包裹本來在版本更新的角度而言,都是一個獨立可隨時更新的檔案庫。若把一個檔案庫
A
放到一個檔案庫 B 裡面去的話,A 會被視作 B 的一部分,因而無法單純用 git pull
來作更新,沒辦法更新,有時意味著一些臭蟲解不掉,而我們使用者根本不知情到底哪裡出了錯誤。因此,我的做法是直接將第三方包裹直接 git clone ROS 工作區間/src
下,這樣我自己的 launch 檔能直接用

$(find [
第三方包裹])
直接自動化找到所需節點或檔案位置,又可以讓第三方包裹得以保持更新。

一個實際的例子,就我個人觀察和感覺(所以請別亂 quote
),就是 ROS 自己本身的架構,加入了某一版本的 OpenCV PCL,當這兩個第三方
libraries
更新版本,使用者想引用更新的實作功能時,才發現ROS 不支援,原因是ROS
內所使用的 libraries 屬於舊版本,如果使用者自己打算繞過這個問題,直接引用較新版的同款 libraries, 則會碰上系統參數衝突。為了這樣的問題大傷腦筋,真的是既浪費時間又沒效率。因此開發者便決定從 ROS Indigo 過後,取消內建的 OpenCV PCL,改由使用者自己安裝,並自行 include 進自己的程式碼內。當初想要大一統囊括所有需求的美意,便因為第三方版本更新的需求,而必須予以更動。但這樣的架構反而能給予使用者更大的開發彈性與便利性。

4. 更新包裹

其實很簡單。cd 進入自己的 ROS 工作空間/src/[某一個包裹],譬如說

$ cd ~/catkin_ws/src/navigation

這樣在版本控制的角度就進入了一個檔案庫當中。再輸入

$ git pull

這樣會更新本地端的檔案庫。接著回到工作空間最頂端的

$ cd ~/catkin_ws

輸入進行編譯,

$ catkin_make

這樣即完成包裹的更新。