【ROS-Navigation】系列(三)——實(shí)戰(zhàn)部署

一、目標(biāo)

搭載Robosense 16線激光雷達(dá)和6軸IMU傳感器的履帶機(jī)器人,通過(guò)使用ros的navigation自主導(dǎo)航框架完成點(diǎn)到點(diǎn)的自主導(dǎo)航

二、總體方案設(shè)計(jì)

2.1 功能架構(gòu)設(shè)計(jì)

Navigation導(dǎo)航框架如下圖所示,其主要完成了全局路徑規(guī)劃器、局部路徑規(guī)劃器、全局代價(jià)地圖、局部代價(jià)地圖和行為決策(recovery_behaviors)的實(shí)現(xiàn)。

由上圖可知,為實(shí)現(xiàn)自主導(dǎo)航功能,還需要地圖、感知、定位、控制這四個(gè)模塊。

2.2 地圖模塊

地圖模塊需要提供全局地圖,以便全局路徑規(guī)劃器進(jìn)行全局路徑規(guī)劃。

全局地圖一般為二維占據(jù)柵格地圖,可由圖像(jpg等格式)表示,其中白色表示自由,黑色表示占據(jù),灰色代表未知區(qū)域。

navigation框架提供了一個(gè)可選的地圖模塊packagemap_server。

package通過(guò)讀取地圖配置文件地圖,然后發(fā)布/map話題,以供全局規(guī)劃器進(jìn)行全局路徑規(guī)劃

地圖配置文件為.yaml文件,主要由6個(gè)參數(shù)描述:

  • 1.地圖路徑
  • 2.地圖分辨率(單位:米)
  • 3.地圖坐標(biāo)系原點(diǎn)(x,y,theta)
  • 4.是否翻轉(zhuǎn)(黑色占據(jù),白色自由 -> 黑色自由,白色占據(jù))
  • 5.占據(jù)閾值
  • 6.自由閾值
image: result.jpg
resolution: 0.20000
origin: [-61, -149.5, 0.000]
negate: 0
occupied_thresh: 0.65
free_thresh: 0.196

地圖.jpg文件,其中白色表示自由,黑色表示占據(jù),一般需要提前讓機(jī)器人用SLAM算法為工作區(qū)域建立二維柵格地圖。。

地圖模塊實(shí)踐操作:

  • 1.建圖

生成二維地圖和yaml配置文件

在實(shí)際工程中一般用3D SLAM算法先建立三維點(diǎn)云地圖,然后設(shè)置地圖分辨率參數(shù),占據(jù)/自由閾值,將其投影為二維柵格地圖,同時(shí)輸出三維點(diǎn)云地圖中坐標(biāo)原點(diǎn)對(duì)應(yīng)二維柵格地圖中的像素坐標(biāo)。

在使用地圖模塊時(shí),需要分清楚機(jī)器人在地圖坐標(biāo)系下的坐標(biāo)和定位坐標(biāo)系下坐標(biāo)的區(qū)別。

機(jī)器人的二維柵格地圖坐標(biāo)系為像素坐標(biāo)系,圖片的左頂點(diǎn)為原點(diǎn),圖片寬度為x,圖片高度為y,定位數(shù)據(jù)通過(guò)地圖分辨率轉(zhuǎn)換為像素坐標(biāo)。

  • 2.定位

若在定位時(shí),使用二維地圖對(duì)應(yīng)的三維點(diǎn)云地圖進(jìn)行定位,則二維地圖坐標(biāo)系與三維點(diǎn)云地圖坐標(biāo)系完成對(duì)應(yīng),機(jī)器人在三維點(diǎn)云地圖坐標(biāo)系下的定位坐標(biāo)可直接作為二維地圖坐標(biāo)系下坐標(biāo)。

若在定位時(shí),未使用二維地圖對(duì)應(yīng)的三維點(diǎn)云地圖進(jìn)行定位,而是使用其它方式,如RTK、UWB等作為定位數(shù)據(jù),則需要在建圖的同時(shí)記錄三維點(diǎn)云地圖中坐標(biāo)原點(diǎn)對(duì)應(yīng)的RTK、UWB值原點(diǎn)對(duì)應(yīng)二維柵格地圖中的像素坐標(biāo)。機(jī)器人在二維地圖坐標(biāo)系下的坐標(biāo)為,實(shí)時(shí)的RTK、UWB值 減去 三維點(diǎn)云地圖中坐標(biāo)原點(diǎn)對(duì)應(yīng)的RTK、UWB值。

2.3 定位模塊

定位方式有多種:①輪速里程計(jì)+imu;②激光+imu;③GPS(RTK)+激光+imu;④GPS(RTK)+激光+imu+輪速里程計(jì);⑤相機(jī)+imu;⑥GPS(RTK)+相機(jī)+imu;⑦GPS(RTK)+相機(jī)+imu+輪速里程計(jì);⑧GPS(RTK)+相機(jī)+激光+imu+輪速里程計(jì);⑨...

以上不同定位方式的定位精度和成本不同,其中⑧的成本最高,定位效果最好;③的應(yīng)用最廣泛,不依賴特定的平臺(tái),同時(shí)環(huán)境適應(yīng)性很強(qiáng)。其它定位方式與具體的場(chǎng)景有關(guān),如室內(nèi)環(huán)境、輪式平臺(tái)等。

Navigation要求定位模塊發(fā)出/odomTopic名稱,消息類型是nav_msgs/Odometry,包含機(jī)器人的位姿和速度。

GPS(RTK)設(shè)備不斷的重新接收和計(jì)算世界坐標(biāo)系中機(jī)器人的位姿,但連續(xù)兩幀的GPS(RTK)坐標(biāo)是不連續(xù)的,可能會(huì)發(fā)生跳變。這意味著在map坐標(biāo)系中機(jī)器人的姿態(tài)再兩幀之間會(huì)發(fā)生離散的跳變。

GPS(RTK)作為長(zhǎng)期的全局坐標(biāo)是很有用的,但是位姿的跳變極大影響運(yùn)動(dòng)規(guī)劃和控制模塊的性能,所以一般不直接使用GPS(RTK)坐標(biāo)進(jìn)行運(yùn)動(dòng)規(guī)劃和控制。

機(jī)器人的里程計(jì)坐標(biāo)是能夠保證連續(xù)的,這意味著在里程計(jì)坐標(biāo)系中的機(jī)器人的姿態(tài)總是平滑變化,沒(méi)有跳變。因此適用于進(jìn)行運(yùn)動(dòng)規(guī)劃和控制。

激光和imu組合成激光里程計(jì),然后通過(guò)GPS(RTK)進(jìn)行校正是常用的定位方法。

定位模塊實(shí)踐操作
1.讓負(fù)責(zé)定位的同學(xué)發(fā)出里程計(jì)坐標(biāo),Topic的名稱是/odom,消息類型是nav_msgs/Odometry,包含機(jī)器人的位姿和速度。

2.如果定位模塊中有tf廣播,需要注釋掉,避免和自己寫的tf沖突。

3.定位模塊發(fā)出的里程計(jì)坐標(biāo)的topicframe_id要綁定到odom固定坐標(biāo)系下(或者直接綁定到map下),不能綁定到base_link坐標(biāo)系下。

2.4 感知模塊

Navigation使用的sensro sources是激光雷達(dá)點(diǎn)云信息,話題名稱是/scan,數(shù)據(jù)類型是LaserScan。

單線激光雷達(dá)可以室內(nèi)滿足要求,但無(wú)法在室外環(huán)境下為機(jī)器人提供足夠的環(huán)境信息。通常使用多線激光雷達(dá)在室外環(huán)境下進(jìn)行環(huán)境感知。

在Navigation中,采用多線激光雷達(dá)在室外環(huán)境下進(jìn)行環(huán)境感知,需要將多線激光雷達(dá)數(shù)據(jù)格式轉(zhuǎn)換為L(zhǎng)aserScan數(shù)據(jù)類型。

推薦用pointcloud_to_laserscan包進(jìn)行數(shù)據(jù)轉(zhuǎn)換。該包是將多線激光雷達(dá)投影為二維數(shù)據(jù),并不是只提取多線激光雷達(dá)中的一條線。

<group ns="bigrobot2">
  <node pkg="pointcloud_to_laserscan" type="pointcloud_to_laserscan_node" name="pointcloud_to_laserscan">
        <rosparam>
            <remap from="cloud_in" to="/lidar_cloud_origin"/>
            target_frame: bigrobot2/base_footprint # Leave disabled to output scan in pointcloud frame
            transform_tolerance: 0.01
            min_height: -0.4
            max_height: 1.0

            angle_min: -3.1415926 # -M_PI
            angle_max: 3.1415926 # M_PI
            angle_increment: 0.003 # 0.17degree
            scan_time: 0.1
            range_min: 0.1
            range_max: 100
            use_inf: true
            inf_epsilon: 1.0

            # Concurrency level, affects number of pointclouds queued for processing and number of threads used
            # 0 : Detect number of cores
            # 1 : Single threaded
            # 2->inf : Parallelism level
            concurrency_level: 1
        </rosparam>
    </node>
</group>

注意1: target_frame: bigrobot2/base_footprint 這個(gè)參數(shù)要求轉(zhuǎn)換前的點(diǎn)云frame_idbigrobot2/base_footprint,而該點(diǎn)云是直接讀取速騰激光雷達(dá)點(diǎn)云topic,所以需要在速騰激光雷達(dá)點(diǎn)云的配置文件中直接修改發(fā)出點(diǎn)云topicframe_idbigrobot2/base_footprint

注意2:rqt_graph顯示pointcloud_to_laserscan沒(méi)有訂閱上points_raw,是因?yàn)闆](méi)有節(jié)點(diǎn)訂閱 scan。必須有節(jié)點(diǎn)訂閱scan,pointcloud_to_laserscan節(jié)點(diǎn)才會(huì)訂閱points_raw

感知模塊實(shí)踐操作

  • 1.修改速騰激光雷達(dá)驅(qū)動(dòng)配置文件,修改雷達(dá)發(fā)出點(diǎn)云topicframe_id為bigrobot2/ lidar_cloud_origin
  • 2.修改pointcloud_to_laserscanlaunch文件中的target_frame為已有tf 樹上的frame_id。
    注意是否需要remap相應(yīng)的topic,可以通過(guò)rosnode info pointcloud_to_laserscan_node查看發(fā)出和接收的topic。
    remapgroup的規(guī)則:先remap,再group。
    remap的規(guī)則:<remap from="old_topic" to="new_topic">

2.5 tf樹

此模塊非常重要!

需要自己創(chuàng)建節(jié)點(diǎn)進(jìn)行tf樹的廣播,以便激光雷達(dá)點(diǎn)云數(shù)據(jù)、里程計(jì)的topic綁定對(duì)應(yīng)的frame_id,必須確保這些topic綁定到對(duì)應(yīng)的frame_id,否則Navigation無(wú)法正確運(yùn)行。

Navigation是通過(guò)ROS中的tf 樹來(lái)維護(hù)機(jī)器人中不同數(shù)據(jù)之間的坐標(biāo)變換,如將激光雷達(dá)點(diǎn)云從激光雷達(dá)坐標(biāo)系(base_laser)變換到車體坐標(biāo)系(base_link)。

一個(gè)機(jī)器人通常tf 樹的結(jié)構(gòu)如下:


tf 樹

每個(gè)坐標(biāo)系都有一個(gè)父坐標(biāo)系和任意子坐標(biāo)系,map坐標(biāo)系是odom坐標(biāo)系的父,odom坐標(biāo)系是base_link的父,每個(gè)坐標(biāo)系只能有一個(gè)父類。

map下可以有多個(gè)定位分支odom,gps(uwb),fusion_localization,這些分支與map原點(diǎn)可以設(shè)定是重合的或者由固定坐標(biāo)轉(zhuǎn)換,采用不同定位方式得到的定位結(jié)果??梢愿鶕?jù)實(shí)際定位效果,把base_link綁定在不同的定位坐標(biāo)系下。

base_link可以綁定在不同分支下

world->map->gps(uwb)->base_link->base_laser
world->map->odom->base_link->base_laser
world->map->fusion_localization->base_link->base_laser

注意,如果slam定位模塊中有tf廣播,需要注釋掉,避免和navigation的tf沖突,ROS只允許一個(gè)tf樹存在。

Rviz中的fixed_frame也是根據(jù)tf樹構(gòu)建的坐標(biāo)樹顯示相應(yīng)的topic。

坐標(biāo)系簡(jiǎn)析

  • 1.世界坐標(biāo)(earth)

固定坐標(biāo)系(fixed frame),用來(lái)描述某點(diǎn)在地球上的絕對(duì)位置,通常用經(jīng)緯度和高度,或者WGS84表示。

引入世界坐標(biāo)系的背景是:
1.可以將機(jī)器人在地圖中的坐標(biāo)通過(guò)earth直接轉(zhuǎn)換為經(jīng)緯高。
2.機(jī)器人建圖時(shí)會(huì)因?yàn)榈貓D過(guò)大(TB甚至PB數(shù)量級(jí))無(wú)法一次性完成建圖,需要將地圖分為多個(gè)子圖(自動(dòng)駕駛地圖就是由多個(gè)子圖組成),可以利用經(jīng)緯高完成不同的子圖拼接。

如果只有一張地圖,一般而言,世界坐標(biāo)系原點(diǎn)與地圖坐標(biāo)系原點(diǎn)重合

  • 2.map坐標(biāo)系
    固定坐標(biāo)系(fixed frame),地圖坐標(biāo)系

作為長(zhǎng)期的全局參考是很有用的,但是跳變使得對(duì)于本地傳感和執(zhí)行器來(lái)說(shuō),其實(shí)是一個(gè)不好的參考坐標(biāo)。

  • 3.里程計(jì)坐標(biāo)系(odom)

odom 坐標(biāo)系是一個(gè)固定坐標(biāo)系(fixed frame)。

odom和map坐標(biāo)系再機(jī)器人運(yùn)動(dòng)開始是重合的。但是,隨著時(shí)間的推移是不重合的,而出現(xiàn)的偏差就是里程計(jì)的累積誤差。

那map–>odom的tf怎么得到?就是在一些校正傳感器合作校正的package比如amcl會(huì)給出一個(gè)位置估計(jì)(localization),這可以得到map–>base_link的tf,所以估計(jì)位置和里程計(jì)位置的偏差也就是odom與map的坐標(biāo)系偏差。所以,如果你的odom計(jì)算沒(méi)有錯(cuò)誤,那么map–>odom的tf就是0。

  • 4.車體坐標(biāo)系(base_link)

該base_link坐標(biāo)剛性地連接到移動(dòng)機(jī)器人基座。base_link可以安裝在基座中的任意方位;對(duì)于每個(gè)硬件平臺(tái),在基座上的不同地方都會(huì)提供一個(gè)明顯的參考點(diǎn)。

機(jī)器人本體坐標(biāo)系,與機(jī)器人中心重合,當(dāng)然有些機(jī)器人(PR 2)是base_footprint,其實(shí)是一個(gè)意思。

  • 5.激光雷達(dá)的坐標(biāo)系(base_laser)
    與激光雷達(dá)的安裝點(diǎn)有關(guān),其與base_link的tf為固定的。

2.6 規(guī)劃模塊

如果以播放bag包形式運(yùn)行move_base,costmap會(huì)報(bào)錯(cuò),costmap的tolorence時(shí)間超過(guò)1s閾值,此時(shí)需要設(shè)置時(shí)間為仿真時(shí)間。

首先啟動(dòng)bag包的播放,讓其發(fā)布/clock話題,這樣其他包就會(huì)從這個(gè)包的時(shí)間戳讀時(shí)間

1 設(shè)置采用仿真時(shí)間
rosparam set /use_sim_time true

2 仿真時(shí)間來(lái)源為bag的時(shí)間戳
rosbag play --pause --clock -k a.bag
--pause:停止播放(按空格取消)
--clock:以bag時(shí)間為clock加,使用仿真時(shí)間
-k, --keep-alive:包的數(shù)據(jù)結(jié)束后,仍然提供時(shí)間服務(wù),避免一些程序讀時(shí)間產(chǎn)生bug

2.7 控制模塊



三、Navigation配置

3.1 move_base.launch

navigation實(shí)際使用的核心在于參數(shù)配置文件!

Navigation由于參數(shù)配置文件不同,在實(shí)際使用過(guò)程中的導(dǎo)航效果也不同,本節(jié)將從launch文件與配置參數(shù)文件進(jìn)行分析,move_base.launch為啟動(dòng)文件,啟動(dòng)的節(jié)點(diǎn)包含map_server、move_base以及pointcloud_to_laserscan。

該launch文件不包含定位節(jié)點(diǎn),需要額外單獨(dú)啟動(dòng),詳情參考另一篇博客navigation定位未加鏈接!

3.2 map_server節(jié)點(diǎn)配置參數(shù)

move_base.launch首先啟動(dòng)map_server節(jié)點(diǎn),加載了104andtest.yaml的地圖配置文件,并設(shè)置map_server發(fā)布的map的frame_idmap

<?xml version="1.0"?>
<launch>
  <node name="map_server" pkg="map_server" type="map_server" args="$(find move_control)/maps/104andtest.yaml">
    <param name="frame_id" value="map"/>
  </node>

104andtest.yaml文件如下,主要是制定了地圖文件和地圖參數(shù)如原點(diǎn),分辨率等.

image: 104andtest.pgm
resolution: 0.050000
origin: [-141.372849, -52.350185, 0.000000]
negate: 0
occupied_thresh: 0.65
free_thresh: 0.196

104andtest.pgm為slam建立的二維地圖,類似

3.3 pointcloud_to_laserscan節(jié)點(diǎn)配置參數(shù)

接著啟動(dòng)pointcloud_to_laserscan節(jié)點(diǎn)

  <node pkg="pointcloud_to_laserscan" type="pointcloud_to_laserscan_node" name="pointcloud_to_laserscan">

    <remap from="/cloud_in" to="/points_raw"/>
    <rosparam>
        target_frame: velodyne # Leave disabled to output scan in pointcloud frame
        <!-- outputxx_frame: base_link -->
        transform_tolerance: 0.01
        min_height: -0.4
        max_height: 1.0

        angle_min: -3.1415926 # -M_PI
        angle_max: 3.1415926 # M_PI
        angle_increment: 0.003 # 0.17degree
        scan_time: 0.1
        range_min: 0.1
        range_max: 100
        use_inf: true
        inf_epsilon: 1.0

        # Concurrency level, affects number of pointclouds queued for processing and number of threads used
        # 0 : Detect number of cores
        # 1 : Single threaded
        # 2->inf : Parallelism level
        concurrency_level: 1
    </rosparam>
<remap from="/scan" to="/scan"/>
</node>

該節(jié)點(diǎn)需要訂閱雷達(dá)點(diǎn)云信息,因?yàn)樵掝}名稱不匹配,需要remap訂閱的話題名稱<remap from="/cloud_in" to="/points_raw"/>

根據(jù)tf關(guān)系決定是否調(diào)整輸出的點(diǎn)云信息的target_frame``,target_frame決定了點(diǎn)云是掛在哪個(gè)tf坐標(biāo)系下的。

min_height:為-0.4,若為0,則會(huì)把地面當(dāng)成障礙物,出現(xiàn)一圈環(huán)形障礙物
max_height:為1.0,高于機(jī)器人本體的高度即可,低于該高度的點(diǎn)云都會(huì)被投影下來(lái)
scan_time:為發(fā)出點(diǎn)云的間隔時(shí)間,0.1s,對(duì)應(yīng)10Hz
range_min:點(diǎn)云距離雷達(dá)最小的距離
range_max:點(diǎn)云距離雷達(dá)最大的距離
use_inf:設(shè)置為true,若為false,可能導(dǎo)致costmap地圖更新會(huì)有問(wèn)題,與costmap_2D的障礙層的inf_is_valid參數(shù)相關(guān)聯(lián),對(duì)于無(wú)窮遠(yuǎn)的點(diǎn)要求其值為inf

3.4 move_base節(jié)點(diǎn)配置參數(shù)

啟動(dòng)核心節(jié)點(diǎn)move_base

<launch>
...
   <node pkg="move_base" type="move_base" respawn="false" name="move_base" output="screen">

     <param name="controller_frequency" value="10.0"/>
     <param name="controller_patiente" value="15.0"/>
     <param name="planner_frequnency" value="0.0"/>
     <param name="planner_patience" value="5.0" />

     <rosparam command="load" file="$(find move_control)/config/global_planner_params.yaml"/>
     <param name="base_global_planner" value="global_planner/GlobalPlanner"/>

     <rosparam command="load" file="$(find move_control)/config/teb_local_planner_params.yaml" />
     <param name="base_local_planner" value="teb_local_planner/TebLocalPlannerROS" />

     <rosparam file="$(find move_control)/config/costmap_common_params.yaml" command="load" ns="global_costmap" />
     <rosparam file="$(find move_control)/config/costmap_common_params.yaml" command="load" ns="local_costmap" />
     <rosparam file="$(find move_control)/config/local_costmap_params.yaml" command="load" />
     <rosparam file="$(find move_control)/config/global_costmap_params.yaml" command="load" />
     <rosparam file="$(find move_control)/config/costmap_converter_params.yaml" command="load" />
 
</launch>

controller_frequency:以 Hz 為單位運(yùn)行控制回路并向地盤發(fā)送速度命令的速率。
controller_patiente:在執(zhí)行空間清理操作之前,控制器將等待多長(zhǎng)時(shí)間(以秒為單位)而沒(méi)有收到有效的控制。
planner_patience:在執(zhí)行空間清理操作之前,規(guī)劃器將在幾秒鐘內(nèi)等待多長(zhǎng)時(shí)間以嘗試找到有效規(guī)劃結(jié)果。
planner_frequnency:以 Hz 為單位運(yùn)行全局規(guī)劃循環(huán)的速率。如果頻率設(shè)置為 0.0,則全局規(guī)劃器將僅在收到新目標(biāo)或本地規(guī)劃器報(bào)告其路徑被阻塞時(shí)運(yùn)行。該參數(shù)是Navigation 1.6.0 中的新功能

3.4.1 base_global_planner節(jié)點(diǎn)配置參數(shù)

global_planner/GlobalPlanner參數(shù)為navigation自帶的全局規(guī)劃器,包含多種規(guī)劃算法.

     <rosparam command="load" file="$(find move_control)/config/global_planner_params.yaml"/>
     <param name="base_global_planner" value="global_planner/GlobalPlanner"/>

global_planner_params.yaml文件如下,其中use_dijkstra若為false,則采用A*算法.

GlobalPlanner:
  allow_unknown: false #true
  default_tolerance: 0.2 # If goal in obstacle, plan to the closest point in radius default_tolerance, default 0.0
  visualize_potential: false 
  use_dijkstra: true #If true, use dijkstra's algorithm. Otherwise, A*.
  use_quadratic: true
  use_grid_path: false
  old_navfn_behavior: false                     # Exactly mirror behavior of navfn, use defaults for other boolean parameters, default false

3.4.2 base_local_planner節(jié)點(diǎn)配置參數(shù)

teb_local_planner/TebLocalPlannerROS為teb局部路徑規(guī)劃器,需要額外安裝,可以參考teb規(guī)劃器未加鏈接

     <rosparam command="load" file="$(find move_control)/config/teb_local_planner_params.yaml" />
     <param name="base_local_planner" value="teb_local_planner/TebLocalPlannerROS" />

teb_local_planner_params.yaml文件如下

TebLocalPlannerROS:

 odom_topic: odom
    
 # Trajectory
  
 teb_autosize: True
 dt_ref: 0.34
 dt_hysteresis: 0.15
 max_samples: 500
 global_plan_overwrite_orientation: True
 allow_init_with_backwards_motion: False # false
 max_global_plan_lookahead_dist: 1.5
 global_plan_viapoint_sep: -1
 global_plan_prune_distance: 1
 exact_arc_length: True
 feasibility_check_no_poses: 5
 publish_feedback: False
    
 # Robot
         
 max_vel_x: 2.0 # 0.8
 max_vel_x_backwards: 0.8
 max_vel_y: 0.0
 max_vel_theta: 0.6
 acc_lim_x: 0.4 # 0.2
 acc_lim_theta: 0.6
 min_turning_radius: 0.0 # diff-drive robot (can turn on place!)

 footprint_model:
#   type: "polygon"
#   vertices: [[-1.223, 0.42], [-1.223, -0.42], [0.3, -0.42], [0.3, 0.42]]
   type: "two_circles"
   front_offset: 0.0
   front_radius: 0.28
   rear_offset: 0.3  
   rear_radius: 0.25

 # GoalTolerance
    
 xy_goal_tolerance: 0.2
 yaw_goal_tolerance: 0.1
 free_goal_vel: False
 complete_global_plan: True
    
 # Obstacles
    
 min_obstacle_dist: 0.1 # 0.25 # This value must also include our robot radius, since footprint_model is set to "point".
 inflation_dist: 0.2 # 0.6
 include_costmap_obstacles: True
 costmap_obstacles_behind_robot_dist: 1.5
 obstacle_poses_affected: 15

 dynamic_obstacle_inflation_dist: 0.2 # 0.6
 include_dynamic_obstacles: True

 costmap_converter_plugin: ""
 costmap_converter_spin_thread: True
 costmap_converter_rate: 5

 # Optimization
    
 no_inner_iterations: 5
 no_outer_iterations: 4
 optimization_activate: True
 optimization_verbose: False
 penalty_epsilon: 0.001 # 0.1
 obstacle_cost_exponent: 4
 weight_max_vel_x: 2
 weight_max_vel_theta: 1
 weight_acc_lim_x: 1
 weight_acc_lim_theta: 1
 weight_kinematics_nh: 1000
 weight_kinematics_forward_drive: 1
 weight_kinematics_turning_radius: 1
 weight_optimaltime: 1 # must be > 0
 weight_shortest_path: 0
 weight_obstacle: 100
 weight_inflation: 0.2
 weight_dynamic_obstacle: 10
 weight_dynamic_obstacle_inflation: 0.2
 weight_viapoint: 1
 weight_adapt_factor: 2

 # Homotopy Class Planner

 enable_homotopy_class_planning: True
 enable_multithreading: True
 max_number_classes: 4
 selection_cost_hysteresis: 1.0
 selection_prefer_initial_plan: 0.9
 selection_obst_cost_scale: 100.0
 selection_alternative_time_cost: False
 
 roadmap_graph_no_samples: 15
 roadmap_graph_area_width: 5
 roadmap_graph_area_length_scale: 1.0
 h_signature_prescaler: 0.5
 h_signature_threshold: 0.1
 obstacle_heading_threshold: 0.45
 switching_blocking_period: 0.0
 viapoints_all_candidates: True
 delete_detours_backwards: True
 max_ratio_detours_duration_best_duration: 3.0
 visualize_hc_graph: False
 visualize_with_time_as_z_axis_scale: False

# Recovery
 
 shrink_horizon_backup: True
 shrink_horizon_min_duration: 10
 oscillation_recovery: True
 oscillation_v_eps: 0.1
 oscillation_omega_eps: 0.1
 oscillation_recovery_min_duration: 10
 oscillation_filter_duration: 10

teb的參數(shù)可分為七類:
Trajectory:局部軌跡的參數(shù),如軌跡長(zhǎng)度,間隔時(shí)間d_t,采樣數(shù)量,是否允許倒退等
Robot:機(jī)器人最大速度,加速度和機(jī)器人外形尺寸
GoalTolerance:到達(dá)目標(biāo)位置的誤差參數(shù)
Obstacles:障礙物距離與膨脹參數(shù)問(wèn)題!!!與costmap中的障礙物膨脹有什么區(qū)別
Optimization:目標(biāo)函數(shù)權(quán)重參數(shù),優(yōu)化求解器參數(shù)
Homotopy Class Planner:同倫類規(guī)劃器,teb中兩種類實(shí)例化局部規(guī)劃器,teb與Homotopy Class Planner.后者是一系列規(guī)劃器的組合.參考
Recovery:類似navigation的recovery模塊,陷入困境時(shí)脫困使用.

teb各個(gè)參數(shù)具體含義及調(diào)整可以參考這篇文章

3.4.3 costmap節(jié)點(diǎn)配置參數(shù)

navigation采用costmap_2D作為地圖層,通過(guò)加載不同參數(shù)生成全局地圖和局部地圖.

     <rosparam file="$(find move_control)/config/costmap_common_params.yaml" command="load" ns="global_costmap" />
     <rosparam file="$(find move_control)/config/costmap_common_params.yaml" command="load" ns="local_costmap" />
     <rosparam file="$(find move_control)/config/local_costmap_params.yaml" command="load" />
     <rosparam file="$(find move_control)/config/global_costmap_params.yaml" command="load" />
     <rosparam file="$(find move_control)/config/costmap_converter_params.yaml" command="load" />

通過(guò)這些參數(shù)文件在ROS的參數(shù)服務(wù)器上注冊(cè)了global_costmap/xxlocal_costmap/xx等參數(shù),move_base中會(huì)調(diào)用costmap_2D的API接口,根據(jù)這些參數(shù)實(shí)例化兩個(gè)costmap對(duì)象,即global_costmap和local_costmap.

costmap_common_params.yaml文件,其中參數(shù)是全局地圖和局部地圖共有的參數(shù).通過(guò)設(shè)置namespace參數(shù)ns="global_costmap"ns="local_costmap"將global_costmap和local_costmap相同的參數(shù)一同初始化,避免改同一個(gè)參數(shù),要修改兩次.

當(dāng)然也可以不用costmap_common_params.yaml文件,把這些參數(shù)全部放到global_costmap_params.yamllocal_costmap_params.yaml文件中.

costmap_common_params.yaml文件如下

robot_radius: 0.3
obstacle_layer:
  enabled: true
  combination_method: 1
  track_unknown_space: true
  obstacle_range: 6
  raytrace_range: 6.1
  observation_sources: scan
  scan: 
    sensor_frame: velodyne
    data_type: LaserScan
    topic: scan
    marking: true
    clearing: true
    inf_is_valid: true
    expected_update_rate: 0

# inflation_layer:
#   enabled:              true
#   cost_scaling_factor:  10.0 # 0.1
#   inflation_radius:     0.8 # 0.01 

static_layer:
  enabled:              true

global_costmap和local_costmap的機(jī)器人尺寸為robot_radius,兩者都包含static_layer和obstacle_layer,而inflation_layer層的配置參數(shù)則由global_costmap和local_costmap分別配置,其中障礙物層參數(shù)解析可見添加鏈接.

global_costmap_params.yaml文件如下,

global_costmap:
  global_frame: map
  robot_base_frame: base_link
  update_frequency: 5.0
  publish_frequency: 5.0
  static_map: true
  rolling_window: false
  resolution: 0.1
  robot_radius: 0.3
  transform_tolerance: 1.0
  map_type: costmap
  plugins:
    - {name: static_layer, type: "costmap_2d::StaticLayer"}
    - {name: obstacle_layer, type: "costmap_2d::ObstacleLayer"}
    - {name: inflation_layer, type: "costmap_2d::InflationLayer"}
  inflation_layer:
    enabled:              true
    cost_scaling_factor:  10.0 # 0.1
    inflation_radius:     0.4 # 0.01 

所有參數(shù)都是global_costmap:的二級(jí)子參數(shù),類似global_costmap/global_frame,參數(shù)解析添加鏈接

local_costmap_params.yaml文件如下

local_costmap:
   global_frame: map
   robot_base_frame: base_link
   update_frequency: 10.0
   publish_frequency: 10.0
   static_map: false
   rolling_window: true
   width: 6.0
   height: 6.0
   resolution: 0.1
   robot_radius: 0.2
   transform_tolerance: 1.0
   plugins:
    - {name: obstacle_layer, type: "costmap_2d::ObstacleLayer"}
    - {name: inflation_layer, type: "costmap_2d::InflationLayer"}
   inflation_layer:
      enabled:              true
      cost_scaling_factor:  10.0 # 0.1
      inflation_radius:     0.2 # 0.01

參數(shù)解析添加鏈接

costmap_converter_params.yaml文件如下

###########################################################################################
## NOTE: Costmap conversion is experimental. Its purpose is to combine many point        ##
## obstales into clusters, computed in a separate thread in order to improve the overall ## 
## efficiency of local planning. However, the implemented conversion algorithms are in a ##
## very early stage of development. Contributions are welcome!                           ##
###########################################################################################

TebLocalPlannerROS:

  ## Costmap converter plugin   
#costmap_converter_plugin: "costmap_converter::CostmapToPolygonsDBSMCCH"
  costmap_converter_plugin: "costmap_converter::CostmapToLinesDBSRANSAC"
#costmap_converter_plugin: "costmap_converter::CostmapToLinesDBSMCCH"
#costmap_converter_plugin: "costmap_converter::CostmapToPolygonsDBSConcaveHull"
  costmap_converter_spin_thread: True
  costmap_converter_rate: 5
 
 
  ## Configure plugins (namespace move_base/costmap_to_lines or move_base/costmap_to_polygons)
  ## costmap_converter/CostmapToLinesDBSRANSAC, costmap_converter/CostmapToLinesDBSMCCH, costmap_converter/CostmapToPolygonsDBSMCCH
  costmap_converter/CostmapToLinesDBSRANSAC:
    cluster_max_distance: 0.4
    cluster_min_pts: 2
    ransac_inlier_distance: 0.15
    ransac_min_inliers: 10
    ransac_no_iterations: 1500
    ransac_remainig_outliers: 3
    ransac_convert_outlier_pts: True
    ransac_filter_remaining_outlier_pts: False
    convex_hull_min_pt_separation: 0.1

costmap_converter誠(chéng)如代碼中的note所說(shuō),還處于very eary stage,早期不穩(wěn)定版本,該參數(shù)不是必須的!

costmap_converter是teb作者提供了一個(gè)插件用于轉(zhuǎn)換代價(jià)地圖,原始的代價(jià)地圖是由柵格地圖中單元格組成,用于表示障礙物,但單元格占用的計(jì)算資源較大,故采用插件將單元格轉(zhuǎn)換成點(diǎn),線,多邊形表示。

可以[參考]這篇文章了解convert(https://blog.csdn.net/weixin_42621524/article/details/120721270)

地圖拼接,新地圖坐標(biāo)系原點(diǎn),相對(duì)舊地圖坐標(biāo)系的變換矩陣。

把odom發(fā)布的cpp文件放到autoware中.

6。問(wèn)題解決
注意pointcloud_to_laserscan是接收到cloud in的 topic后才會(huì)創(chuàng)建去訂閱
remap不成功,在cloudin前面加了個(gè)/,不知道能否起作用
https://blog.csdn.net/qq_23670601/article/details/88529739

參考:
坐標(biāo)系:https://blog.csdn.net/lovely_yoshino/article/details/99699321

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容