1. 程式人生 > >ROS話題訂閱與namespace使用出現的問題彙總

ROS話題訂閱與namespace使用出現的問題彙總

1    什麼情況下會用到namespace(以下簡稱ns)

當我們需要運行同一個pkg的同一個node,雖然可以在launch檔案中給他們命名成不同的name但是,我們希望使用<group ns=""></group>來更加清晰的區分他們之間的不同。但是加上ns後,常常會出現以下問題,需要我們解決。比如,原先不新增ns的時候一切執行正常,但是當我們新增ns後,無法執行等一類問題。

2    理解什麼是namespace

ns就是把你原先執行的pkg---node放到一個名稱空間中去,這個名稱空間就是ns,例如:

<launch>
    <group ns="name1">
        <node pkg="your_pkg" type="your_node_name" name="whatever" />
    </group>
    <group ns="name2">
        <node pkg="your_pkg" type="your_node_name" name="whatever" />
    </group>
</launch>

我們執行的pkg---node---name都可以一樣,但是必須在不同的ns中,這樣ROS才可以區分他們,否則會認為重複,第二個node會覆蓋掉第一個node,這樣始終只有一個node在執行。

在rosnode list 你可以看到:

/name1/whatever
/name2/whatever

而在rostopic list中,所有話題也會被追加上name1和name2

3    新增namespace後提示tf,no laser scan data等問題

這就是由於第二2節中的ns改變了原來會話題的名字。例如,在新增ns之前,該node需要訂閱  /scan的雷達資料,但是新增ns後,雷達的資料釋出的話題追加了ns的名稱空間,變成了/name1/scan ,這時候你再訂閱/scan,肯定是沒有資料的,因為不存在/scan這個話題了,雷達釋出的資料話題從/scan變成了/name1/scan。解決辦法是使用<remap from="/name1/scan" to="/scan" />,這樣的重對映才會使得資料訂閱釋出之間重新構建正確的關係。

同樣,你可以通過檢視rqt_graph來確認你的node是否都正確的訂閱了你的話題,哪些需要remap的,可以很清晰的查閱到。

4    發現你的話題無論怎麼remap,rqt_graph都不發生改變,還是原來的話題

這看起來顯示remap失效了,然而執行launch時沒有報錯,又表明你的話題引數都是存在切正確的。

沒錯,這個也困擾了我很久。

4.1    在使用remap時。要注意remap的作用範圍,remap只能在<node />,<group /><launch />

如果你放在<include />裡面不會報錯也沒有警告,但是命令列會顯示說,“無效的remap”仔細看可以看到。

注意這裡說的在<node />,<group /><launch />下可以有效的使用remap,是在直接tag標籤下,間接地也是不行的。例如:

<launch>
    .......
    <remap from="xx" to="xx" />
</launch>

這個叫做在<launch>標籤下直接使用,是合法有效的。

但是下面這種就是在<launch>標籤下間接使用,在<include>下直接使用,這樣是無效的。但是執行不會提示error和warnning。這一點要十分注意。

<launch>
    .......
    <include file="$(find pkg)/.....">
        <remap from="xx" to="xx" />
    </include>
</launch>

4.2    在解決4.1的正確使用remap後,如果問題仍然沒有解決,那麼就是你的remap沒有正確的尋找到你的話題

這是由於你的話題,你沒有使用絕對路徑導致的。例如:

<launch>
    <node pkg="your_pkg" type="your_node_name" name="whatever">
        <remap from="name1/scan" to="scan" />
    </node>
</launch>

這樣remap後,如果你的話題沒有成功的建立訂閱關係,即讓rqt_graph的圖中name1/scan話題還存在,你的訂閱沒有連線到/scan話題上,那麼就是話題的絕對路徑導致的ROS系統未能找到指定的話題,這個在執行launch時也不會有error和warnning提示。解決辦法就是在話題前加上“/”即可。例如:

<launch>
    <node pkg="your_pkg" type="your_node_name" name="whatever">
        <remap from="/name1/scan" to="/scan" />
    </node>
</launch>

這樣新增上“/”,話題的路徑就變成絕對路徑了。問題就解決了。

5    從yaml檔案像launch檔案傳遞引數

5.1    什麼是yaml檔案

這個概念自行查詢。總結來說就是,yaml檔案存放的是一個字典(可以粗糙的這樣理解,不完全合理!),它有鍵值對成對出現,同樣也可以是巢狀的字典。例如

1.yaml

var1: 12
var2: name
var3: base_link

2.yaml

var1: 2323
var2: {
scan_frame: robot0_laser0
topic: robot0/laser_0
}
var3: robot0

1.yaml是比較典型的沒有巢狀,2.yaml中的var2是巢狀,他的值又是由一個字典組成。

5.2    yaml檔案中的所有的鍵都可以理解成變數,值就是這些變數的初始值,是可以通過rosparam set改變的。當我們在launch檔案中load這個yaml檔案時就是,將這些變數新增到ROS的引數伺服器,並且按照yaml檔案中的值,給這些變數賦予初始值。

這就不難理解了,yaml檔案中的建就是ROS引數伺服器中的引數。因此在launch檔案中,load一個yaml檔案後,可以直接通過<param name=" " value=" " />來修改yaml檔案中的值,

<launch>
    <rosparam file="$(find your_pkg)/1.yaml"  command="load" />
    <param name="var1"   value="1222222" />
</launch>

這樣就實現了yaml檔案像launch檔案傳遞引數的功能:

當然你也可以這樣:

<launch>
<arg name="var1_value" default="33333" />
    <rosparam file="$(find your_pkg)/1.yaml"  command="load" />
    <param name="var1"   value="$(arg var1_value)" />
</launch>

在ROS的官網,官方也給出了一種方法,我測試過和上面的效果一樣。

如下所示:

rosparam 有一個屬性叫做subst_value,如果設定成true就可以直接修改yaml檔案中的引數預設值。

例子如下:

<launch>
    <arg name="whitelist" default="[3, 2]"/>
    <rosparam commond="load" file="$(find your_pkg)/...">
    <rosparam param="whitelist" subst_value="True">$(arg whitelist)</rosparam>
</launch>

這也是完全正確的。